
#include <map>
#include <cmath>
#include <BColorf>
#include <BPainter>
#include <BOpenGL>

#include "member_BFont.h"
#include "member_BStyle.h"
#include "member_BCamera.h"
#include "member_BWidget.h"
#include "member_BTexture.h"
#include "member_BImage.h"
#include "member_BPixmap.h"
#include "member_BGlyph.h"
#include "member_BPainter.h"
#include "member_BProgram.h"
#include "IGlobal.h"

using namespace BWE;

#define member					(*(member_BPainter*)_ptr)
#define member_allocate()		_ptr = new member_BPainter(this)
#define member_release()		delete (member_BPainter*)_ptr

BPainter::BPainter(const BSize& size)
{
	member_allocate();
	member.save();

	member.size = size;

	setClip(size);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
BPainter::BPainter(const BWidget* widget)
{
	member_allocate();
	member.save();

	member.widget = widget;
	member.size = widget_member(widget)->size;
	member.state = widget_member(widget)->state;

	setClip(member.size);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
BPainter::BPainter(const BPixmap* pixmap)
{
	member_allocate();
	member.save();

	member.pixmap = pixmap;
	member.size = pixmap->size();
	
	setClip(member.size);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
BPainter::BPainter(const BGlyph* graphic)
{
	member_allocate();
	member.save();

	member.graphic = graphic;
	member.size = graphic->size();

	setClip(member.size);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
BPainter::~BPainter()
{
	if (const BProgram* program = member.program)
		program_member(program)->unuse();
	member.open();
	member_release();
}

const BWidget* BPainter::widget() const
{
	return member.widget;
}
State BPainter::state() const
{
	if (!member.state.enabled)
		return State_Disable;
	if (member.state.actived)
		return State_Actived;
	return State_Normal;
}

void BPainter::setClip(int x, int y, int width, int height)
{
	setClip(BRecti(x, y, width, height));
}
void BPainter::setClip(const BRecti& clip)
{
	if (member.clip != clip)
	{
		member.clip = clip;
		glViewport(clip.x(), member.size.height() - clip.bottom(), clip.width(), clip.height());
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(clip.left(), clip.right() , clip.bottom(), clip.top(), -1, 1);
		glMatrixMode(GL_MODELVIEW);
	}
}
const BRecti& BPainter::clip() const
{
	return member.clip;
}

void BPainter::pushAttrib()
{
	glPushAttrib(GL_ALL_ATTRIB_BITS);
}
void BPainter::popAttrib()
{
	glPopAttrib();
	member.cullback = glIsEnabled(GL_CULL_FACE);
	member.polySmooth = glIsEnabled(GL_MULTISAMPLE);
	member.lineSmooth = glIsEnabled(GL_LINE_SMOOTH);
	member.pointSmooth = glIsEnabled(GL_POINT_SMOOTH);
	glGetFloatv(GL_POINT_SIZE, &member.pointSize);
	glGetFloatv(GL_LINE_WIDTH, &member.lineWidth);
	glGetIntegerv(GL_LINE_STIPPLE, &member.lineStipple);
}

void BPainter::pushMatrix()
{
	glPushMatrix();
}
const BMatrix& BPainter::matrix() const
{
#ifdef REAL_IS_DOUBLE
	glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&member.matrix);
#else
	glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&member.matrix);
#endif
	return member.matrix;
}
void BPainter::popMatrix()
{
	glPopMatrix();
}

void BPainter::translate(int tx, int ty, int tz)
{
	glTranslatef((float)tx, (float)ty, (float)tz);
}
void BPainter::translate(const BPointi& pos, int tz)
{
	glTranslatef((float)pos.x(), (float)pos.y(), (float)tz);
}
void BPainter::rotate(int angle, int ax, int ay, int az)
{
	glRotatef((float)angle, (float)ax, (float)ay, (float)az);
}
void BPainter::scale(int sx, int sy, int sz)
{
	glScalef((float)sx, (float)sy, (float)sz);
	member.scale *= (sx + sy) * BReal(0.5);
}
void BPainter::scale(const BPointi& scale, int sz)
{
	glScalef((float)scale.x(), (float)scale.y(), (float)sz);
	member.scale *= (scale.x() + scale.y()) * BReal(0.5);
}

void BPainter::translate(float tx, float ty, float tz)
{
	glTranslatef(tx, ty, tz);
}
void BPainter::translate(const BPointf& pos, float tz)
{
	glTranslatef(pos.x(), pos.y(), tz);
}
void BPainter::rotate(float angle, float ax, float ay, float az)
{
	glRotatef(angle, ax, ay, az);
}
void BPainter::scale(float sx, float sy, float sz)
{
	glScalef(sx, sy, sz);
	member.scale *= (sx + sy) * BReal(0.5);
}
void BPainter::scale(const BPointf& scale, float sz)
{
	glScalef(scale.x(), scale.y(), sz);
	member.scale *= (scale.x() + scale.y()) * BReal(0.5);
}

void BPainter::translate(double tx, double ty, double tz)
{
	glTranslated(tx, ty, tz);
}
void BPainter::translate(const BPointd& pos, double tz)
{
	glTranslated(pos.x(), pos.y(), tz);
}
void BPainter::rotate(double angle, double ax, double ay, double az)
{
	glRotated(angle, ax, ay, az);
}
void BPainter::scale(double sx, double sy, double sz)
{
	glScaled(sx, sy, sz);
	member.scale *= (sx + sy) * BReal(0.5);
}
void BPainter::scale(const BPointd& scale, double sz)
{
	glScaled(scale.x(), scale.y(), sz);
	member.scale *= (scale.x() + scale.y()) * BReal(0.5);
}

void BPainter::translation() const
{

}
void BPainter::rotatation() const
{

}
BReal BPainter::scaling() const
{
	return member.scale;
}

bool BPainter::setColor(StyleColor name, State state) const
{
	if (const BColor* color = member.findColor(name + state))
	{
		member.color = *color;
		glColor4ub(color->r(), color->g(), color->b(), color->a());
		return true;
	}
	return false;
}
bool BPainter::setColor(const char* colorName) const
{
	if (const BColor* color = member.findColor(colorName))
	{
		member.color = *color;
		glColor4ub(color->r(), color->g(), color->b(), color->a());
		return true;
	}
	return false;
}
bool BPainter::setColor(const BString& colorName) const
{
	if (const BColor* color = member.findColor(colorName))
	{
		member.color = *color;
		glColor4ub(color->r(), color->g(), color->b(), color->a());
		return true;
	}
	return false;
}

bool BPainter::setColor(BByte r, BByte g, BByte b, BByte a) const
{
	if (a > 1)
	{
		member.color.set(r, g, b, a);
		glColor4ub(r, g, b, a);
		return true;
	}
	return false;
}
bool BPainter::setColor(const BColor& color) const
{
	if (color.a())
	{
		member.color = color;
		glColor4ub(color.r(), color.g(), color.b(), color.a());
		return true;
	}
	return false;
}
const BColor& BPainter::color() const
{
	return member.color;
}

const BColor& BPainter::color(StyleColor name, State state) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->colorMap.find(name + state);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->colorMap.find(name + state);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->colorMap(name + state);
}
const BColor& BPainter::color(const char* name) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->namedColorMap.find(name);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->namedColorMap.find(name);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->namedColorMap(name);
}
const BColor& BPainter::color(const BString& name) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->namedColorMap.find(name);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->namedColorMap.find(name);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->namedColorMap(name);
}

const BImage* BPainter::image(StyleImage name, State state) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->imageMap.find(name + state);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->imageMap.find(name + state);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->imageMap(name + state);
}
const BImage* BPainter::image(const char* name) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->namedImageMap.find(name);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->namedImageMap.find(name);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->namedImageMap(name);
}
const BImage* BPainter::image(const BString& name) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->namedImageMap.find(name);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->namedImageMap.find(name);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->namedImageMap(name);
}

const BValue& BPainter::value(StyleImage name, State state) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->valueMap.find(name + state);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->valueMap.find(name + state);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->valueMap(name + state);
}
const BValue& BPainter::value(const char* name) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->namedValueMap.find(name);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->namedValueMap.find(name);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->namedValueMap(name);
}
const BValue& BPainter::value(const BString& name) const
{
	if (const BStyle* style = member.style)
	{
		auto it = style_member(style)->namedValueMap.find(name);
		if (it.valid())
			return *it;
	}
	else if (const BStyle* style = member.state.style)
	{
		auto it = style_member(style)->namedValueMap.find(name);
		if (it.valid())
			return *it;
	}
	return style_member(app_style)->namedValueMap(name);
}

bool BPainter::bind(StyleImage name, State state)
{
	if (const BImage* image = member.findImage(name + state))
	{
		return bind(image);
	}
	return false;
}
bool BPainter::bind(const BTexture* texture, const BRectf& rect)
{
	if (member.pixmap && member.pixmap == texture)
		return false;
	GLuint tbo = 0;
	if (texture && texture->enabled())
	{
		if (texture_member(texture)->dirty)
			texture->flush();
		tbo = texture_member(texture)->tbo;
	}
	if (member.tbo != tbo)
	{
		member.tbo = tbo;
		if (tbo)
		{
			member.tsize = texture->size();
			member.trect = rect;
			if (member.trect.empty())
			{
				member.trect = member.tsize;
			}
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, tbo);
			if (texture_member(texture)->blend == BTexture::Blend_Modulate)
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			if (texture_member(texture)->blend == BTexture::Blend_Replace)
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
			if (texture_member(texture)->blend == BTexture::Blend_Decal)
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
			if (texture_member(texture)->blend == BTexture::Blend_Color)
			{
				const BColor& color = texture_member(texture)->blendColor;
				BColorf colorf(color.a() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f);
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
				glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&color);
			}
		}
		else
		{
			member.tsize.reset();
			member.trect.reset();
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
		}
	}
	return member.tbo;
}
bool BPainter::bind(const BWidget* widget, const BRectf& rect)
{
	if (member.widget && member.widget == widget)
		return false;
	GLuint tbo = 0;
	if (widget)
	{
		tbo = widget_member(widget)->tbo;
		//IWindow* window = widget_member(widget)->window;
		//if (widget_member(widget)->dirty && window)
		//{
		//	widget_member(widget)->frame(window->msfbo, GL_COLOR_ATTACHMENT2);
		//}
	}
	if (member.tbo != tbo)
	{
		member.tbo = tbo;
		if (tbo)
		{
			member.tsize = widget->size();
			member.trect = rect;
			if (member.trect.empty())
			{
				member.trect = member.tsize;
			}
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, tbo);
		}
		else
		{
			member.tsize.reset();
			member.trect.reset();
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
		}
	}
	return member.tbo;
}
bool BPainter::bind(const BCamera* camera, const BRectf& rect)
{
	GLuint tbo = 0;
	if (camera)
	{
		tbo = camera_member(camera)->tbo;
	}
	if (member.tbo != tbo)
	{
		member.tbo = tbo;
		if (tbo)
		{
			member.tsize = camera->pixelSize();
			member.trect = rect;
			if (member.trect.empty())
			{
				member.trect = member.tsize;
			}
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, tbo);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
		}
		else
		{
			member.tsize.reset();
			member.trect.reset();
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
		}
	}
	return member.tbo;
}
void BPainter::unbind()
{
	if (member.tbo)
	{
		member.tbo = 0;
		member.tsize.reset();
		member.trect.reset();
		glBindTexture(GL_TEXTURE_2D, 0);
		glDisable(GL_TEXTURE_2D);
	}
}

void BPainter::setProgram(const BProgram* program)
{
	if (member.program != program)
	{
		if (const BProgram* program = member.program)
			program_member(program)->unuse();
		member.program = program;
		if (program && program->enabled())
			program_member(program)->use();
	}
}
const BProgram* BPainter::program() const
{
	return member.program;
}

void BPainter::setStyle(const BStyle* style)
{
	if (member.style != style)
	{
		member.style = style;
	}
}
const BStyle* BPainter::style() const
{
	return member.style;
}
const BStyle* BPainter::realStyle() const
{
	if (member.style)
	{
		return member.style;
	}
	if (member.state.style)
	{
		return member.state.style;
	}
	return app_style;
}

void BPainter::setFont(const BFont* font)
{
	if (member.font != font)
	{
		member.font = font;
	}
}
const BFont* BPainter::font() const
{
	return member.font;
}
const BFont* BPainter::realFont() const
{
	if (member.font)
	{
		return member.font;
	}
	if (member.style)
	{
		if (const BFont* font = member.style->value(Value_Font))
			return font;
	}
	if (member.state.style)
	{
		if (const BFont* font = member.state.style->value(Value_Font))
			return font;
	}
	if (const BFont* font = app_style->value(Value_Font))
	{
		return font;
	}
	return app_font;
}

void BPainter::setPointSmooth(bool pointSmooth)
{
	if (pointSmooth)
	{
		glEnable(GL_POINT_SMOOTH);
	}
	else
	{
		glDisable(GL_POINT_SMOOTH);
	}
	member.pointSmooth = pointSmooth;
}
bool BPainter::pointSmooth() const
{
	return member.pointSmooth;
}

void BPainter::setPointSize(float size)
{
	if (member.pointSize != size)
	{
		member.pointSize = size;
		glPointSize(size);
	}
}
float BPainter::pointSize() const
{
	return member.pointSize;
}

void BPainter::setLineStipple(BUShort stipple)
{
	if (member.lineStipple != stipple)
	{
		member.lineStipple = stipple;
		if (stipple > 0)
		{
			glEnable(GL_LINE_STIPPLE);
			glLineStipple(1, stipple);
		}
		else
		{
			glDisable(GL_LINE_STIPPLE);
		}
	}
}
BUShort BPainter::stipple() const
{
	return member.lineStipple;
}

void BPainter::setCullback(bool cullback)
{
	if (cullback)
	{
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
	}
	else
	{
		glDisable(GL_CULL_FACE);
	}
	member.cullback = cullback;
}
bool BPainter::cullback() const
{
	return member.cullback;
}

void BPainter::setLineSmooth(bool lineSmooth)
{
	if (member.lineSmooth != lineSmooth)
	{
		member.lineSmooth = lineSmooth;
		if (lineSmooth)
		{
			glEnable(GL_LINE_SMOOTH);
		}
		else
		{
			glDisable(GL_LINE_SMOOTH);
		}
	}
}
bool BPainter::lineSmooth() const
{
	return member.lineSmooth;
}

void BPainter::setLineWidth(float lineWidth)
{
	if (member.lineWidth != lineWidth)
	{
		member.lineWidth = lineWidth;
		glLineWidth(lineWidth);
	}
}
float BPainter::lineWidth() const
{
	return member.lineWidth;
}

void BPainter::setPolySmooth(bool polySmooth)
{
	if (member.polySmooth != polySmooth)
	{
		member.polySmooth = polySmooth;
		if (polySmooth)
			glEnable(GL_MULTISAMPLE);
		else
			glDisable(GL_MULTISAMPLE);
	}
}
bool BPainter::polySmooth() const
{
	return member.polySmooth;
}

void BPainter::drawPoint(int x, int y) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2i(x, y);
		glEnd();
	}
}
void BPainter::drawPoint(float x, float y) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2f(x, y);
		glEnd();
	}
}
void BPainter::drawPoint(double x, double y) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2d(x, y);
		glEnd();
	}
}

void BPainter::drawPoint(const BPointi& point) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2i(point.x(), point.y());
		glEnd();
	}
}
void BPainter::drawPoint(const BPointf& point) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2f(point.x(), point.y());
		glEnd();
	}
}
void BPainter::drawPoint(const BPointd& point) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2d(point.x(), point.y());
		glEnd();
	}
}

void BPainter::drawPoints(const BPointi* points, int size) const
{
	if (points && size > 0)
	{
		glBegin(GL_POINTS);
		for (int i = 0; i < size; i++)
		{
			const BPointi& point = points[i];
			glVertex2i(point.x(), point.y());
		}
		glEnd();
	}
}
void BPainter::drawPoints(const BPointf* points, int size) const
{
	if (points && size > 0)
	{
		glBegin(GL_POINTS);
		for (int i = 0; i < size; i++)
		{
			const BPointf& point = points[i];
			glVertex2f(point.x(), point.y());
		}
		glEnd();
	}
}
void BPainter::drawPoints(const BPointd* points, int size) const
{
	if (points && size > 0)
	{
		glBegin(GL_POINTS);
		for (int i = 0; i < size; i++)
		{
			const BPointd& point = points[i];
			glVertex2d(point.x(), point.y());
		}
		glEnd();
	}
}

void BPainter::drawPoints(const BPointiArray& points) const
{
	if (points.size() > 0)
	{
		glBegin(GL_POINTS);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointi& point = points[i];
			glVertex2i(point.x(), point.y());
		}
		glEnd();
	}
}
void BPainter::drawPoints(const BPointfArray& points) const
{
	if (points.size() > 0)
	{
		glBegin(GL_POINTS);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointf& point = points[i];
			glVertex2f(point.x(), point.y());
		}
		glEnd();
	}
}
void BPainter::drawPoints(const BPointdArray& points) const
{
	if (points.size() > 0)
	{
		glBegin(GL_POINTS);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointd& point = points[i];
			glVertex2d(point.x(), point.y());
		}
		glEnd();
	}
}

void BPainter::drawLine(int x0, int y0, int x1, int y1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2i(x0, y0);
		glVertex2i(x1, y1);
		glEnd();
	}
}
void BPainter::drawLine(float x0, float y0, float x1, float y1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glEnd();
	}
}
void BPainter::drawLine(double x0, double y0, double x1, double y1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2d(x0, y0);
		glVertex2d(x1, y1);
		glEnd();
	}
}

void BPainter::drawLine(const BPointi& p0, const BPointi& p1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glEnd();
	}
}
void BPainter::drawLine(const BPointf& p0, const BPointf& p1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glEnd();
	}
}
void BPainter::drawLine(const BPointd& p0, const BPointd& p1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glEnd();
	}
}

void BPainter::drawLines(const BPointi* points, int size) const
{
	size /= 2;
	glBegin(GL_LINES);
	for (int i = 0; i < size; i++)
	{
		glVertex2i(points[i * 2 + 0].x(), points[i * 2 + 0].y());
		glVertex2i(points[i * 2 + 1].x(), points[i * 2 + 1].y());
	}
	glEnd();
}
void BPainter::drawLines(const BPointf* points, int size) const
{
	size /= 2;
	glBegin(GL_LINES);
	for (int i = 0; i < size; i++)
	{
		glVertex2f(points[i * 2 + 0].x(), points[i * 2 + 0].y());
		glVertex2f(points[i * 2 + 1].x(), points[i * 2 + 1].y());
	}
	glEnd();
}
void BPainter::drawLines(const BPointd* points, int size) const
{
	size /= 2;
	glBegin(GL_LINES);
	for (int i = 0; i < size; i++)
	{
		glVertex2d(points[i * 2 + 0].x(), points[i * 2 + 0].y());
		glVertex2d(points[i * 2 + 1].x(), points[i * 2 + 1].y());
	}
	glEnd();
}

void BPainter::drawLines(const BPointiArray& points) const
{
	drawLines(points.data(), points.size());
}
void BPainter::drawLines(const BPointfArray& points) const
{
	drawLines(points.data(), points.size());
}
void BPainter::drawLines(const BPointdArray& points) const
{
	drawLines(points.data(), points.size());
}

void BPainter::drawLineLoop(const BPointi* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < size; i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointf* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < size; i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointd* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < size; i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawLineLoop(const BPointiArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointfArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointdArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawLineStrip(const BPointi* points, int size) const
{
	if (size > 1)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < size; i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointf* points, int size) const
{
	if (size > 1)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < size; i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointd* points, int size) const
{
	if (size > 1)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < size; i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawLineStrip(const BPointiArray& points) const
{
	if (points.size() > 1)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointfArray& points) const
{
	if (points.size() > 1)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointdArray& points) const
{
	if (points.size() > 1)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2i(x0, y0);
		glVertex2i(x1, y1);
		glVertex2i(x2, y2);
		glEnd();
	}
}
void BPainter::drawTriangle(float x0, float y0, float x1, float y1, float x2, float y2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glVertex2f(x2, y2);
		glEnd();
	}
}
void BPainter::drawTriangle(double x0, double y0, double x1, double y1, double x2, double y2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2d(x0, y0);
		glVertex2d(x1, y1);
		glVertex2d(x2, y2);
		glEnd();
	}
}

void BPainter::drawTriangle(const BPointi& p0, const BPointi& p1, const BPointi& p2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glEnd();
	}
}
void BPainter::drawTriangle(const BPointf& p0, const BPointf& p1, const BPointf& p2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glEnd();
	}
}
void BPainter::drawTriangle(const BPointd& p0, const BPointd& p1, const BPointd& p2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glEnd();
	}
}

void BPainter::fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2i(x0, y0);
	glVertex2i(x1, y1);
	glVertex2i(x2, y2);
	glEnd();
}
void BPainter::fillTriangle(float x0, float y0, float x1, float y1, float x2, float y2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2f(x0, y0);
	glVertex2f(x1, y1);
	glVertex2f(x2, y2);
	glEnd();
}
void BPainter::fillTriangle(double x0, double y0, double x1, double y1, double x2, double y2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2d(x0, y0);
	glVertex2d(x1, y1);
	glVertex2d(x2, y2);
	glEnd();
}

void BPainter::fillTriangle(const BPointi& p0, const BPointi& p1, const BPointi& p2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2i(p0.x(), p0.y());
	glVertex2i(p1.x(), p1.y());
	glVertex2i(p2.x(), p2.y());
	glEnd();
}
void BPainter::fillTriangle(const BPointf& p0, const BPointf& p1, const BPointf& p2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2f(p0.x(), p0.y());
	glVertex2f(p1.x(), p1.y());
	glVertex2f(p2.x(), p2.y());
	glEnd();
}
void BPainter::fillTriangle(const BPointd& p0, const BPointd& p1, const BPointd& p2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2d(p0.x(), p0.y());
	glVertex2d(p1.x(), p1.y());
	glVertex2d(p2.x(), p2.y());
	glEnd();
}

void BPainter::drawTriangles(const BPointi* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < size; i += 3)
		{
			const BPointi& p0 = points[i];
			const BPointi& p1 = points[i + 1];
			const BPointi& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointf* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < size; i += 3)
		{
			const BPointf& p0 = points[i];
			const BPointf& p1 = points[i + 1];
			const BPointf& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointd* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < size; i += 3)
		{
			const BPointd& p0 = points[i];
			const BPointd& p1 = points[i + 1];
			const BPointd& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::drawTriangles(const BPointiArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < points.size(); i += 3)
		{
			const BPointi& p0 = points[i];
			const BPointi& p1 = points[i + 1];
			const BPointi& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointfArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < points.size(); i += 3)
		{
			const BPointf& p0 = points[i];
			const BPointf& p1 = points[i + 1];
			const BPointf& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointdArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < points.size(); i += 3)
		{
			const BPointd& p0 = points[i];
			const BPointd& p1 = points[i + 1];
			const BPointd& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::fillTriangles(const BPointi* points, int size) const
{
	if (size < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			const BPointi& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			const BPointi& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointf* points, int size) const
{
	if (size < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			const BPointf& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointd* points, int size) const
{
	if (size < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			const BPointd& p = points[i];
			float tx = float(p.x() - member.trect.x()) * ratioX;
			float ty = float(p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::fillTriangles(const BPointiArray& points) const
{
	if (points.size() < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointi& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointfArray& points) const
{
	if (points.size() < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointf& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointdArray& points) const
{
	if (points.size() < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointd& p = points[i];
			float tx = float(p.x() - member.trect.x()) * ratioX;
			float ty = float(p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::fillTriangleFan(const BPointi* points, int size) const
{
	if (size < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < size; i++)
		{
			const BPointi& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < size; i++)
		{
			const BPointi& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleFan(const BPointf* points, int size) const
{
	if (size < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < size; i++)
		{
			const BPointf& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < size; i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleFan(const BPointd* points, int size) const
{
	if (size < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < size; i++)
		{
			const BPointd& p = points[i];
			float tx = float(p.x() - member.trect.x()) * ratioX;
			float ty = float(p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < size; i++)
		{
			const BPointd& p = points[i];
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
}

void BPainter::fillTriangleFan(const BPointiArray& points) const
{
	if (points.size() < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointi& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointi& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleFan(const BPointfArray& points) const
{
	if (points.size() < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointf& p = points[i];
			float tx = (p.x() - member.trect.x()) * ratioX;
			float ty = (p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleFan(const BPointdArray& points) const
{
	if (points.size() < 3)
		return;
	if (member.tbo && member.trect.valid())
	{
		float ratioX = 1.0f / member.trect.width();
		float ratioY = 1.0f / member.trect.height();
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointd& p = points[i];
			float tx = float(p.x() - member.trect.x()) * ratioX;
			float ty = float(p.y() - member.trect.y()) * ratioX;
			glTexCoord2f(tx, ty);
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
	else
	{
		glBegin(GL_TRIANGLE_FAN);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointd& p = points[i];
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
}

void BPainter::drawTriangleStrip(const BPointi* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < size; i++)
		{
			const BPointi& p0 = points[i - 2];
			const BPointi& p1 = points[i - 1];
			const BPointi& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointf* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < size; i++)
		{
			const BPointf& p0 = points[i - 2];
			const BPointf& p1 = points[i - 1];
			const BPointf& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointd* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < size; i++)
		{
			const BPointd& p0 = points[i - 2];
			const BPointd& p1 = points[i - 1];
			const BPointd& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::drawTriangleStrip(const BPointiArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < points.size(); i++)
		{
			const BPointi& p0 = points[i - 2];
			const BPointi& p1 = points[i - 1];
			const BPointi& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointfArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < points.size(); i++)
		{
			const BPointf& p0 = points[i - 2];
			const BPointf& p1 = points[i - 1];
			const BPointf& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointdArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < points.size(); i++)
		{
			const BPointd& p0 = points[i - 2];
			const BPointd& p1 = points[i - 1];
			const BPointd& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::fillTriangleStrip(const BPointi* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < size; i++)
		{
			const BPointi& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointf* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < size; i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointd* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < size; i++)
		{
			const BPointd& p = points[i];
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
}

void BPainter::fillTriangleStrip(const BPointiArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointi& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointfArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointdArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointd& p = points[i];
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
}

void BPainter::drawRect(const BRecti& rect) const
{
	drawRect(rect.x(), rect.y(), rect.width(), rect.height());
}
void BPainter::drawRect(const BRectf& rect) const
{
	drawRect(rect.x(), rect.y(), rect.width(), rect.height());
}
void BPainter::drawRect(const BRectd& rect) const
{
	drawRect(rect.x(), rect.y(), rect.width(), rect.height());
}

void BPainter::drawRect(const BPointi& pos, const BSizei& size) const
{
	drawRect(pos.x(), pos.y(), size.width(), size.height());
}
void BPainter::drawRect(const BPointf& pos, const BSizef& size) const
{
	drawRect(pos.x(), pos.y(), size.width(), size.height());
}
void BPainter::drawRect(const BPointd& pos, const BSized& size) const
{
	drawRect(pos.x(), pos.y(), size.width(), size.height());
}

void BPainter::drawRect(int x, int y, int width, int height) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2i(x, y);
		glVertex2i(x, y + height);
		glVertex2i(x + width, y + height);
		glVertex2i(x + width, y);
		glEnd();
	}
}
void BPainter::drawRect(float x, float y, float width, float height) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2f(x, y);
		glVertex2f(x, y + height);
		glVertex2f(x + width, y + height);
		glVertex2f(x + width, y);
		glEnd();
	}
}
void BPainter::drawRect(double x, double y, double width, double height) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2d(x, y);
		glVertex2d(x, y + height);
		glVertex2d(x + width, y + height);
		glVertex2d(x + width, y);
		glEnd();
	}
}

void BPainter::fillRect(const BRecti& rect) const
{
	fillRect(rect.x(), rect.y(), rect.width(), rect.height());
}
void BPainter::fillRect(const BRectf& rect) const
{
	fillRect(rect.x(), rect.y(), rect.width(), rect.height());
}
void BPainter::fillRect(const BRectd& rect) const
{
	fillRect(rect.x(), rect.y(), rect.width(), rect.height());
}

void BPainter::fillRect(const BPointi& pos, const BSizei& size) const
{
	fillRect(pos.x(), pos.y(), size.width(), size.height());
}
void BPainter::fillRect(const BPointf& pos, const BSizef& size) const
{
	fillRect(pos.x(), pos.y(), size.width(), size.height());
}
void BPainter::fillRect(const BPointd& pos, const BSized& size) const
{
	fillRect(pos.x(), pos.y(), size.width(), size.height());
}

void BPainter::fillRect(int x, int y, int width, int height) const
{
	if (width < 1 || height < 1)
		return;
	if (member.tbo)
	{
		glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(x, y);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(x, y + height);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(x + width, y + height);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(x + width, y);
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
			glVertex2i(x, y);
			glVertex2i(x, y + height);
			glVertex2i(x + width, y + height);
			glVertex2i(x + width, y);
		glEnd();
	}
}
void BPainter::fillRect(float x, float y, float width, float height) const
{
	if (member.tbo)
	{
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);		glVertex2f(x, y);
		glTexCoord2f(0.0f, 0.0f);		glVertex2f(x, y + height);
		glTexCoord2f(1.0f, 0.0f);		glVertex2f(x + width, y + height);
		glTexCoord2f(1.0f, 1.0f);		glVertex2f(x + width, y);
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2f(x, y);
		glVertex2f(x, y + height);
		glVertex2f(x + width, y + height);
		glVertex2f(x + width, y);
		glEnd();
	}
}
void BPainter::fillRect(double x, double y, double width, double height) const
{
	if (member.tbo)
	{
		glBegin(GL_QUADS);
		glTexCoord2d(0.0, 1.0);		glVertex2d(x, y);
		glTexCoord2d(0.0, 0.0);		glVertex2d(x, y + height);
		glTexCoord2d(1.0, 0.0);		glVertex2d(x + width, y + height);
		glTexCoord2d(1.0, 1.0);		glVertex2d(x + width, y);
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2d(x, y);
		glVertex2d(x, y + height);
		glVertex2d(x + width, y + height);
		glVertex2d(x + width, y);
		glEnd();
	}
}

void BPainter::fillRect(const BRecti& rect, const BRecti& tile) const
{
	if (rect.empty())
		return;
	if (member.tbo)
	{
		float tx0 = (float)tile.left() / member.tsize.width();
		float ty0 = (float)tile.top() / member.tsize.height();
		float tx1 = (float)tile.right() / member.tsize.width();
		float ty1 = (float)tile.bottom() / member.tsize.height();
		glBegin(GL_QUADS);
		glTexCoord2f(tx0, ty0);		glVertex2i(rect.left(), rect.top());
		glTexCoord2f(tx0, ty1);		glVertex2i(rect.left(), rect.bottom());
		glTexCoord2f(tx1, ty1);		glVertex2i(rect.right(), rect.bottom());
		glTexCoord2f(tx1, ty0);		glVertex2i(rect.right(), rect.top());
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2i(rect.left(), rect.top());
		glVertex2i(rect.left(), rect.bottom());
		glVertex2i(rect.right(), rect.bottom());
		glVertex2i(rect.right(), rect.top());
		glEnd();
	}
}
void BPainter::fillRect(const BRectf& rect, const BRectf& tile) const
{
	if (rect.empty())
		return;
	if (member.tbo)
	{
		float tx0 = tile.left() / member.tsize.width();
		float ty0 = tile.top() / member.tsize.height();
		float tx1 = tile.right() / member.tsize.width();
		float ty1 = tile.bottom() / member.tsize.height();
		glBegin(GL_QUADS);
		glTexCoord2f(tx0, ty0);		glVertex2f(rect.left(), rect.top());
		glTexCoord2f(tx0, ty1);		glVertex2f(rect.left(), rect.bottom());
		glTexCoord2f(tx1, ty1);		glVertex2f(rect.right(), rect.bottom());
		glTexCoord2f(tx1, ty0);		glVertex2f(rect.right(), rect.top());
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2f(rect.left(), rect.top());
		glVertex2f(rect.left(), rect.bottom());
		glVertex2f(rect.right(), rect.bottom());
		glVertex2f(rect.right(), rect.top());
		glEnd();
	}
}
void BPainter::fillRect(const BRectd& rect, const BRectd& tile) const
{
	if (rect.empty())
		return;
	if (member.tbo)
	{
		double tx0 = tile.left() / member.tsize.width();
		double ty0 = tile.top() / member.tsize.height();
		double tx1 = tile.right() / member.tsize.width();
		double ty1 = tile.bottom() / member.tsize.height();
		glBegin(GL_QUADS);
		glTexCoord2d(tx0, ty0);		glVertex2d(rect.left(), rect.top());
		glTexCoord2d(tx0, ty1);		glVertex2d(rect.left(), rect.bottom());
		glTexCoord2d(tx1, ty1);		glVertex2d(rect.right(), rect.bottom());
		glTexCoord2d(tx1, ty0);		glVertex2d(rect.right(), rect.top());
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2d(rect.left(), rect.top());
		glVertex2d(rect.left(), rect.bottom());
		glVertex2d(rect.right(), rect.bottom());
		glVertex2d(rect.right(), rect.top());
		glEnd();
	}
}

void BPainter::fillRect(const BPointi& pos, const BSizei& size, const BRecti& tile) const
{
	fillRect(pos.x(), pos.y(), size.width(), size.height(), tile);
}
void BPainter::fillRect(const BPointf& pos, const BSizef& size, const BRectf& tile) const
{
	fillRect(pos.x(), pos.y(), size.width(), size.height(), tile);
}
void BPainter::fillRect(const BPointd& pos, const BSized& size, const BRectd& tile) const
{
	fillRect(pos.x(), pos.y(), size.width(), size.height(), tile);
}

void BPainter::fillRect(int x, int y, int width, int height, const BRecti& tile) const
{
	if (width < 1 || height < 1)
		return;
	if (member.tbo)
	{
		float tx0 = (float)tile.left() / member.tsize.width();
		float ty0 = (float)tile.top() / member.tsize.height();
		float tx1 = (float)tile.right() / member.tsize.width();
		float ty1 = (float)tile.bottom() / member.tsize.height();
		glBegin(GL_QUADS);
		glTexCoord2f(tx0, ty0);		glVertex2i(x, y);
		glTexCoord2f(tx0, ty1);		glVertex2i(x, y + height);
		glTexCoord2f(tx1, ty1);		glVertex2i(x + width, y + height);
		glTexCoord2f(tx1, ty0);		glVertex2i(x + width, y);
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2i(x, y);
		glVertex2i(x, y + height);
		glVertex2i(x + width, y + height);
		glVertex2i(x + width, y);
		glEnd();
	}
}
void BPainter::fillRect(float x, float y, float width, float height, const BRectf& tile) const
{
	if (width < 1 || height < 1)
		return;
	if (member.tbo)
	{
		float tx0 = tile.left() / member.tsize.width();
		float ty0 = tile.top() / member.tsize.height();
		float tx1 = tile.right() / member.tsize.width();
		float ty1 = tile.bottom() / member.tsize.height();
		glBegin(GL_QUADS);
		glTexCoord2f(tx0, ty0);		glVertex2f(x, y);
		glTexCoord2f(tx0, ty1);		glVertex2f(x, y + height);
		glTexCoord2f(tx1, ty1);		glVertex2f(x + width, y + height);
		glTexCoord2f(tx1, ty0);		glVertex2f(x + width, y);
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2f(x, y);
		glVertex2f(x, y + height);
		glVertex2f(x + width, y + height);
		glVertex2f(x + width, y);
		glEnd();
	}
}
void BPainter::fillRect(double x, double y, double width, double height, const BRectd& tile) const
{
	if (width < 1 || height < 1)
		return;
	if (member.tbo)
	{
		double tx0 = tile.left() / member.tsize.width();
		double ty0 = tile.top() / member.tsize.height();
		double tx1 = tile.right() / member.tsize.width();
		double ty1 = tile.bottom() / member.tsize.height();
		glBegin(GL_QUADS);
		glTexCoord2d(tx0, ty0);		glVertex2d(x, y);
		glTexCoord2d(tx0, ty1);		glVertex2d(x, y + height);
		glTexCoord2d(tx1, ty1);		glVertex2d(x + width, y + height);
		glTexCoord2d(tx1, ty0);		glVertex2d(x + width, y);
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
		glVertex2d(x, y);
		glVertex2d(x, y + height);
		glVertex2d(x + width, y + height);
		glVertex2d(x + width, y);
		glEnd();
	}
}

void BPainter::fillRect(const BRecti& rect, const BMargin& margin)
{
	if (member.tbo)
	{
		int top = margin.top();
		int left = margin.left();
		int right = margin.right();
		int bottom = margin.bottom();

		BRect crect = rect;
		crect.left() += left;
		crect.top() += top;
		crect.right() -= right;
		crect.bottom() -= bottom;

		int tw = (int)member.tsize.width();
		int th = (int)member.tsize.height();

		fillRect(rect.left(), crect.top(), left, crect.height(), BRecti(0, top, left, th - top - bottom));
		fillRect(crect.left(), rect.top(), crect.width(), top, BRecti(left, 0, tw - left - right, top));
		fillRect(crect.right(), crect.top(), right, crect.height(), BRecti(tw - left, top, right, th - top - bottom));
		fillRect(crect.left(), crect.bottom(), crect.width(), bottom, BRecti(left, th - bottom, tw - left - right, bottom));

		fillRect(rect.left(), rect.top(), left, top, BRecti(0, 0, left, top));
		fillRect(crect.right(), rect.top(), right, top, BRecti(tw - right, 0, right, top));
		fillRect(rect.left(), crect.bottom(), left, bottom, BRecti(0, th - bottom, left, bottom));
		fillRect(crect.right(), crect.bottom(), right, bottom, BRecti(tw - right, th - bottom, right, bottom));

		fillRect(crect, BRecti(left, top, tw - left - right, th - top - bottom));
	}
	else
	{
		fillRect(rect);
	}
}
void BPainter::fillRect(const BRectf& rect, const BMargin& margin)
{
	if (member.tbo)
	{
		float top = (float)margin.top();
		float left = (float)margin.left();
		float right = (float)margin.right();
		float bottom = (float)margin.bottom();

		BRectf crect = rect;
		crect.left() += left;
		crect.top() += top;
		crect.right() -= right;
		crect.bottom() -= bottom;

		float tw = (float)member.tsize.width();
		float th = (float)member.tsize.height();

		fillRect(rect.left(), crect.top(), left, crect.height(), BRectf(0, top, left, th - top - bottom));
		fillRect(crect.left(), rect.top(), crect.width(), top, BRectf(left, 0, tw - left - right, top));
		fillRect(crect.right(), crect.top(), right, crect.height(), BRectf(tw - left, top, right, th - top - bottom));
		fillRect(crect.left(), crect.bottom(), crect.width(), bottom, BRectf(left, th - bottom, tw - left - right, bottom));

		fillRect(rect.left(), rect.top(), left, top, BRectf(0, 0, left, top));
		fillRect(crect.right(), rect.top(), right, top, BRectf(tw - right, 0, right, top));
		fillRect(rect.left(), crect.bottom(), left, bottom, BRectf(0, th - bottom, left, bottom));
		fillRect(crect.right(), crect.bottom(), right, bottom, BRectf(tw - right, th - bottom, right, bottom));

		fillRect(crect, BRectf(left, top, tw - left - right, th - top - bottom));
	}
	else
	{
		fillRect(rect);
	}
}
void BPainter::fillRect(const BRectd& rect, const BMargin& margin)
{
	if (member.tbo)
	{
		double top = margin.top();
		double left = margin.left();
		double right = margin.right();
		double bottom = margin.bottom();

		BRectd crect = rect;
		crect.left() += left;
		crect.top() += top;
		crect.right() -= right;
		crect.bottom() -= bottom;

		double tw = (double)member.tsize.width();
		double th = (double)member.tsize.height();

		fillRect(rect.left(), crect.top(), left, crect.height(), BRectd(0, top, left, th - top - bottom));
		fillRect(crect.left(), rect.top(), crect.width(), top, BRectd(left, 0, tw - left - right, top));
		fillRect(crect.right(), crect.top(), right, crect.height(), BRectd(tw - left, top, right, th - top - bottom));
		fillRect(crect.left(), crect.bottom(), crect.width(), bottom, BRectd(left, th - bottom, tw - left - right, bottom));

		fillRect(rect.left(), rect.top(), left, top, BRectd(0, 0, left, top));
		fillRect(crect.right(), rect.top(), right, top, BRectd(tw - right, 0, right, top));
		fillRect(rect.left(), crect.bottom(), left, bottom, BRectd(0, th - bottom, left, bottom));
		fillRect(crect.right(), crect.bottom(), right, bottom, BRectd(tw - right, th - bottom, right, bottom));

		fillRect(crect, BRectd(left, top, tw - left - right, th - top - bottom));
	}
	else
	{
		fillRect(rect);
	}
}

void BPainter::fillRect(const BPointi& pos, const BSizei& size, const BMargin& margin)
{
	fillRect(BRecti(pos, size), margin);
}
void BPainter::fillRect(const BPointf& pos, const BSizef& size, const BMargin& margin)
{
	fillRect(BRectf(pos, size), margin);
}
void BPainter::fillRect(const BPointd& pos, const BSized& size, const BMargin& margin)
{
	fillRect(BRectd(pos, size), margin);
}

void BPainter::fillRect(int x, int y, int width, int height, const BMargin& margin)
{
	fillRect(BRecti(x, y, width, height), margin);
}
void BPainter::fillRect(float x, float y, float width, float height, const BMargin& margin)
{
	fillRect(BRectf(x, y, width, height), margin);
}
void BPainter::fillRect(double x, double y, double width, double height, const BMargin& margin)
{
	fillRect(BRectf(x, y, width, height), margin);
}

void BPainter::drawRoundRect(const BRecti& rect, int rx, int ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, (float)rx, (float)ry);
	drawLineLoop(member.floatPoints);
	
}
void BPainter::drawRoundRect(const BRectf& rect, float rx, float ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, rx, ry);
	drawLineLoop(member.floatPoints);

}
void BPainter::drawRoundRect(const BRectd& rect, double rx, double ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, rx, ry);
	drawLineLoop(member.doublePoints);
}

void BPainter::drawRoundRect(const BPointi& pos, const BSizei& size, int rx, int ry) const
{
	drawRoundRect(BRecti(pos, size), rx, ry);
}
void BPainter::drawRoundRect(const BPointf& pos, const BSizef& size, float rx, float ry) const
{
	drawRoundRect(BRectf(pos, size), rx, ry);
}
void BPainter::drawRoundRect(const BPointd& pos, const BSized& size, double rx, double ry) const
{
	drawRoundRect(BRectd(pos, size), rx, ry);
}

void BPainter::drawRoundRect(int x, int y, int width, int height, int rx, int ry) const
{
	drawRoundRect(BRecti(x, y, width, height), rx, ry);
}
void BPainter::drawRoundRect(float x, float y, float width, float height, float rx, float ry) const
{
	drawRoundRect(BRectf(x, y, width, height), rx, ry);
}
void BPainter::drawRoundRect(double x, double y, double width, double height, double rx, double ry) const
{
	drawRoundRect(BRectd(x, y, width, height), rx, ry);
}

void BPainter::fillRoundRect(const BRecti& rect, int rx, int ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, (float)rx, (float)ry);
	fillPolygon(member.floatPoints);
}
void BPainter::fillRoundRect(const BRectf& rect, float rx, float ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, rx, ry);
	fillPolygon(member.floatPoints);
}
void BPainter::fillRoundRect(const BRectd& rect, double rx, double ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, rx, ry);
	fillPolygon(member.doublePoints);
}

void BPainter::fillRoundRect(const BPointi& pos, const BSizei& size, int rx, int ry) const
{
	fillRoundRect(BRecti(pos, size), rx, ry);
}
void BPainter::fillRoundRect(const BPointf& pos, const BSizef& size, float rx, float ry) const
{
	fillRoundRect(BRectf(pos, size), rx, ry);
}
void BPainter::fillRoundRect(const BPointd& pos, const BSized& size, double rx, double ry) const
{
	fillRoundRect(BRectd(pos, size), rx, ry);
}

void BPainter::fillRoundRect(int x, int y, int width, int height, int rx, int ry) const
{
	fillRoundRect(BRecti(x, y, width, height), rx, ry);
}
void BPainter::fillRoundRect(float x, float y, float width, float height, float rx, float ry) const
{
	fillRoundRect(BRectf(x, y, width, height), rx, ry);
}
void BPainter::fillRoundRect(double x, double y, double width, double height, double rx, double ry) const
{
	fillRoundRect(BRectd(x, y, width, height), rx, ry);
}

void BPainter::drawQuad(const BPointi& p0, const BPointi& p1, const BPointi& p2, const BPointi& p3) const
{
	glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
	glEnd();
}
void BPainter::drawQuad(const BPointf& p0, const BPointf& p1, const BPointf& p2, const BPointf& p3) const
{
	glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
	glEnd();
}
void BPainter::drawQuad(const BPointd& p0, const BPointd& p1, const BPointd& p2, const BPointd& p3) const
{
	glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
	glEnd();
}

void BPainter::fillQuad(const BPointi& p0, const BPointi& p1, const BPointi& p2, const BPointi& p3) const
{
	glBegin(GL_QUADS);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
	glEnd();
}
void BPainter::fillQuad(const BPointf& p0, const BPointf& p1, const BPointf& p2, const BPointf& p3) const
{
	glBegin(GL_QUADS);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
	glEnd();
}
void BPainter::fillQuad(const BPointd& p0, const BPointd& p1, const BPointd& p2, const BPointd& p3) const
{
	glBegin(GL_QUADS);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
	glEnd();
}

void BPainter::drawQuads(const BPointi* points, int size)
{
	size -= 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i+= 4)
	{
		const BPointi& p0 = points[i];
		const BPointi& p1 = points[i + 1];
		const BPointi& p2 = points[i + 2];
		const BPointi& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointf* points, int size)
{
	size -= 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointf& p0 = points[i];
		const BPointf& p1 = points[i + 1];
		const BPointf& p2 = points[i + 2];
		const BPointf& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointd* points, int size)
{
	size -= 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointd& p0 = points[i];
		const BPointd& p1 = points[i + 1];
		const BPointd& p2 = points[i + 2];
		const BPointd& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
		glEnd();
	}
}

void BPainter::drawQuads(const BPointiArray& points)
{
	int size = points.size() - 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointi& p0 = points[i];
		const BPointi& p1 = points[i + 1];
		const BPointi& p2 = points[i + 2];
		const BPointi& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointfArray& points)
{
	int size = points.size() - 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointf& p0 = points[i];
		const BPointf& p1 = points[i + 1];
		const BPointf& p2 = points[i + 2];
		const BPointf& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointdArray& points)
{
	int size = points.size() - 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointd& p0 = points[i];
		const BPointd& p1 = points[i + 1];
		const BPointd& p2 = points[i + 2];
		const BPointd& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
		glEnd();
	}
}

void BPainter::fillQuads(const BPointi* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointi& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointf* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointd* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::fillQuads(const BPointiArray& points)
{
	int size = points.size() - 3;
	if (size < 0)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointi& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointfArray& points)
{
	int size = points.size() - 3;
	if (size < 0)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointdArray& points)
{
	int size = points.size() - 3;
	if (size < 0)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::fillQuadStrip(const BPointi* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < size; i++)
	{
		const BPointi& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointf* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < size; i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointd* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < size; i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::fillQuadStrip(const BPointiArray& points)
{
	if (points.size() < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < points.size(); i++)
	{
		const BPointi& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointfArray& points)
{
	if (points.size() < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < points.size(); i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointdArray& points)
{
	if (points.size() < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < points.size(); i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::drawEllipse(const BPointi& center, int radiusX, int radiusY) const
{
	float rx2 = (float)radiusX * radiusX;
	float ry2 = (float)radiusY * radiusY;
	glBegin(GL_LINE_LOOP);
	for (int x = radiusX; x > -radiusX; x -= 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() + y);
	}
	for (int x = -radiusX; x <= radiusX; x += 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() - y);
	}
	glEnd();
}
void BPainter::drawEllipse(int x, int y, int width, int height) const
{
	int hw = width / 2;
	int hh = height / 2;
	drawEllipse(BPointi(x + hw, y + hh), hw, hh);
}
void BPainter::drawEllipse(const BPointi& pos, const BSizei& size) const
{
	int hw = size.width() / 2;
	int hh = size.height() / 2;
	drawEllipse(pos + BPointi(hw, hh), hw, hh);
}
void BPainter::drawEllipse(const BRecti& rect) const
{
	drawEllipse(rect.center(), rect.width() / 2, rect.height() / 2);
}

void BPainter::fillEllipse(const BPointi& center, int radiusX, int radiusY) const
{
	float rx2 = (float)radiusX * radiusX;
	float ry2 = (float)radiusY * radiusY;
	glBegin(GL_POLYGON);
	for (int x = radiusX; x > -radiusX; x -= 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() + y);
	}
	for (int x = -radiusX; x <= radiusX; x += 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() - y);
	}
	glEnd();
}
void BPainter::fillEllipse(int x, int y, int width, int height) const
{
	int hw = width / 2;
	int hh = height / 2;
	fillEllipse(BPointi(x + hw, y + hh), hw, hh);
}
void BPainter::fillEllipse(const BPointi& pos, const BSizei& size) const
{
	int hw = size.width() / 2;
	int hh = size.height() / 2;
	fillEllipse(pos + BPointi(hw, hh), hw, hh);
}
void BPainter::fillEllipse(const BRecti& rect) const
{
	fillEllipse(rect.center(), rect.width() / 2, rect.height() / 2);
}

void BPainter::drawPolygon(const BPointi* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < size; i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::drawPolygon(const BPointf* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < size; i++)
	{
		glVertex2f(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::drawPolygon(const BPointd* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < size; i++)
	{
		glVertex2d(points[i].x(), points[i].y());
	}
	glEnd();
}

void BPainter::fillPolygon(const BPointi* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for (int i = 0; i < size; i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::fillPolygon(const BPointf* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for (int i = 0; i < size; i++)
	{
		glVertex2f(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::fillPolygon(const BPointd* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for (int i = 0; i < size; i++)
	{
		glVertex2d(points[i].x(), points[i].y());
	}
	glEnd();
}

void BPainter::drawPolygon(const BPointiArray& points) const
{
	if (points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::drawPolygon(const BPointfArray& points) const
{
	if (points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex2f(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::drawPolygon(const BPointdArray& points) const
{
	if (points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex2d(points[i].x(), points[i].y());
	}
	glEnd();
}

void BPainter::fillPolygon(const BPointiArray& points) const
{
	if (points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::fillPolygon(const BPointfArray& points) const
{
	if (points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex2f(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::fillPolygon(const BPointdArray& points) const
{
	if (points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex2d(points[i].x(), points[i].y());
	}
	glEnd();
}

void BPainter::drawArc(int cx, int cy, int radius, int begin, int end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_LINE_STRIP);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawArc(float cx, float cy, float radius, float begin, float end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_LINE_STRIP);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawArc(double cx, double cy, double radius, double begin, double end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	double first = bDTR(begin);
	double last = bDTR(end);
	double sr = (last - first) / sides;
	glBegin(GL_LINE_STRIP);
	for (int i = 0; i <= sides; i++)
	{
		double angle = first + i * sr;
		double x = cos(angle) * radius;
		double y = sin(angle) * radius;
		glVertex2d(cx + x, cy + y);
	}
	glEnd();
}

void BPainter::drawArc(const BPointi& center, int radius, int begin, int end, int sides) const
{
	drawArc(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::drawArc(const BPointf& center, float radius, float begin, float end, int sides) const
{
	drawArc(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::drawArc(const BPointd& center, double radius, double begin, double end, int sides) const
{
	drawArc(center.x(), center.y(), radius, begin, end, sides);
}

void BPainter::fillArc(int cx, int cy, const BRangei& radius, int begin, int end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius.mid() * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float c = cos(angle);
		float s = sin(angle);
		glVertex2f(cx + c * radius.min(), cy + s * radius.min());
		glVertex2f(cx + c * radius.max(), cy + s * radius.max());
	}
	glEnd();
}
void BPainter::fillArc(float cx, float cy, const BRangef& radius, float begin, float end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius.mid() * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float c = cos(angle);
		float s = sin(angle);
		glVertex2f(cx + c * radius.min(), cy + s * radius.min());
		glVertex2f(cx + c * radius.max(), cy + s * radius.max());
	}
	glEnd();
}
void BPainter::fillArc(double cx, double cy, const BRanged& radius, double begin, double end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius.mid() * member.scale), 12, 24);
	double first = bDTR(begin);
	double last = bDTR(end);
	double sr = (last - first) / sides;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i <= sides; i++)
	{
		double angle = first + i * sr;
		double c = cos(angle);
		double s = sin(angle);
		glVertex2d(cx + c * radius.min(), cy + s * radius.min());
		glVertex2d(cx + c * radius.max(), cy + s * radius.max());
	}
	glEnd();
}

void BPainter::fillArc(const BPointi& center, const BRangei& radius, int begin, int end, int sides) const
{
	fillArc(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::fillArc(const BPointf& center, const BRangef& radius, float begin, float end, int sides) const
{
	fillArc(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::fillArc(const BPointd& center, const BRanged& radius, double begin, double end, int sides) const
{
	fillArc(center.x(), center.y(), radius, begin, end, sides);
}

void BPainter::drawChord(int cx, int cy, int radius, int begin, int end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawChord(float cx, float cy, float radius, float begin, float end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawChord(double cx, double cy, double radius, double begin, double end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	double first = bDTR(begin);
	double last = bDTR(end);
	double sr = (last - first) / sides;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i <= sides; i++)
	{
		double angle = first + i * sr;
		double x = cos(angle) * radius;
		double y = sin(angle) * radius;
		glVertex2d(cx + x, cy + y);
	}
	glEnd();
}

void BPainter::drawChord(const BPointi& center, int radius, int begin, int end, int sides) const
{
	drawChord(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::drawChord(const BPointf& center, float radius, float begin, float end, int sides) const
{
	drawChord(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::drawChord(const BPointd& center, double radius, double begin, double end, int sides) const
{
	drawChord(center.x(), center.y(), radius, begin, end, sides);
}

void BPainter::fillChord(int cx, int cy, int radius, int begin, int end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_POLYGON);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::fillChord(float cx, float cy, float radius, float begin, float end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_POLYGON);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::fillChord(double cx, double cy, double radius, double begin, double end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	double first = bDTR(begin);
	double last = bDTR(end);
	double sr = (last - first) / sides;
	glBegin(GL_POLYGON);
	for (int i = 0; i <= sides; i++)
	{
		double angle = first + i * sr;
		double x = cos(angle) * radius;
		double y = sin(angle) * radius;
		glVertex2d(cx + x, cy + y);
	}
	glEnd();
}

void BPainter::fillChord(const BPointi& center, int radius, int begin, int end, int sides) const
{
	fillChord(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::fillChord(const BPointf& center, float radius, float begin, float end, int sides) const
{
	fillChord(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::fillChord(const BPointd& center, double radius, double begin, double end, int sides) const
{
	fillChord(center.x(), center.y(), radius, begin, end, sides);
}

void BPainter::drawPie(int cx, int cy, int radius, int begin, int end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_LINE_LOOP);
	glVertex2i(cx, cy);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawPie(float cx, float cy, float radius, float begin, float end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_LINE_LOOP);
	glVertex2f(cx, cy);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawPie(double cx, double cy, double radius, double begin, double end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	double first = bDTR(begin);
	double last = bDTR(end);
	double sr = (last - first) / sides;
	glBegin(GL_LINE_LOOP);
	glVertex2d(cx, cy);
	for (int i = 0; i <= sides; i++)
	{
		double angle = first + i * sr;
		double x = cos(angle) * radius;
		double y = sin(angle) * radius;
		glVertex2d(cx + x, cy + y);
	}
	glEnd();
}

void BPainter::drawPie(const BPointi& center, int radius, int begin, int end, int sides) const
{
	drawPie(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::drawPie(const BPointf& center, float radius, float begin, float end, int sides) const
{
	drawPie(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::drawPie(const BPointd& center, double radius, double begin, double end, int sides) const
{
	drawPie(center.x(), center.y(), radius, begin, end, sides);
}

void BPainter::fillPie(int cx, int cy, int radius, int begin, int end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_POLYGON);
	glVertex2i(cx, cy);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::fillPie(float cx, float cy, float radius, float begin, float end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float first = bDTR(begin);
	float last = bDTR(end);
	float sr = (last - first) / sides;
	glBegin(GL_POLYGON);
	glVertex2f(cx, cy);
	for (int i = 0; i <= sides; i++)
	{
		float angle = first + i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::fillPie(double cx, double cy, double radius, double begin, double end, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	double first = bDTR(begin);
	double last = bDTR(end);
	double sr = (last - first) / sides;
	glBegin(GL_POLYGON);
	glVertex2d(cx, cy);
	for (int i = 0; i <= sides; i++)
	{
		double angle = first + i * sr;
		double x = cos(angle) * radius;
		double y = sin(angle) * radius;
		glVertex2d(cx + x, cy + y);
	}
	glEnd();
}

void BPainter::fillPie(const BPointi& center, int radius, int begin, int end, int sides) const
{
	fillPie(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::fillPie(const BPointf& center, float radius, float begin, float end, int sides) const
{
	fillPie(center.x(), center.y(), radius, begin, end, sides);
}
void BPainter::fillPie(const BPointd& center, double radius, double begin, double end, int sides) const
{
	fillPie(center.x(), center.y(), radius, begin, end, sides);
}

void BPainter::drawCircle(int cx, int cy, int radius, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float sr = PI2f / sides;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < sides; i++)
	{
		float angle = i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawCircle(float cx, float cy, float radius, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float sr = PI2f / sides;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < sides; i++)
	{
		float angle = i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::drawCircle(double cx, double cy, double radius, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	double sr = PI2f / sides;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < sides; i++)
	{
		double angle = i * sr;
		double x = cos(angle) * radius;
		double y = sin(angle) * radius;
		glVertex2d(cx + x, cy + y);
	}
	glEnd();
}

void BPainter::drawCircle(const BPointi& center, int radius, int sides) const
{
	drawCircle(center.x(), center.y(), radius, sides);
}
void BPainter::drawCircle(const BPointf& center, float radius, int sides) const
{
	drawCircle(center.x(), center.y(), radius, sides);
}
void BPainter::drawCircle(const BPointd& center, double radius, int sides) const
{
	drawCircle(center.x(), center.y(), radius, sides);
}

void BPainter::fillCircle(int cx, int cy, int radius, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float sr = PI2f / sides;
	glBegin(GL_POLYGON);
	if (member.tbo)
	{
		float ratio = 0.5f / radius;
		for (int i = 0; i < sides; i++)
		{
			float angle = i * sr;
			float x = cos(angle) * radius;
			float y = sin(angle) * radius;
			float tx = 0.5f + x * ratio;
			float ty = 0.5f + y * ratio;
			glTexCoord2f(tx, ty);
			glVertex2f(cx + x, cy + y);
		}
	}
	else
	{
		for (int i = 0; i < sides; i++)
		{
			float angle = i * sr;
			float x = cos(angle) * radius;
			float y = sin(angle) * radius;
			glVertex2f(cx + x, cy + y);
		}
	}
	glEnd();
}
void BPainter::fillCircle(float cx, float cy, float radius, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	float sr = PI2f / sides;
	glBegin(GL_POLYGON);
	if (member.tbo)
	{
		float ratio = 0.5f / radius;
		for (int i = 0; i < sides; i++)
		{
			float angle = i * sr;
			float x = cos(angle) * radius;
			float y = sin(angle) * radius;
			float tx = 0.5f + x * ratio;
			float ty = 0.5f + y * ratio;
			glTexCoord2f(tx, ty);
			glVertex2f(cx + x, cy + y);
		}
	}
	else
	{
		for (int i = 0; i < sides; i++)
		{
			float angle = i * sr;
			float x = cos(angle) * radius;
			float y = sin(angle) * radius;
			glVertex2f(cx + x, cy + y);
		}
	}
	glEnd();
}
void BPainter::fillCircle(double cx, double cy, double radius, int sides) const
{
	if (sides < 3)
		sides = bClamp(int(radius * member.scale), 12, 24);
	double sr = PI2d / sides;
	glBegin(GL_POLYGON);
	if (member.tbo)
	{
		double ratio = 0.5f / radius;
		for (int i = 0; i < sides; i++)
		{
			double angle = i * sr;
			double x = cos(angle) * radius;
			double y = sin(angle) * radius;
			double tx = 0.5f + x * ratio;
			double ty = 0.5f + y * ratio;
			glTexCoord2d(tx, ty);
			glVertex2d(cx + x, cy + y);
		}
	}
	else
	{
		for (int i = 0; i < sides; i++)
		{
			double angle = i * sr;
			double x = cos(angle) * radius;
			double y = sin(angle) * radius;
			glVertex2d(cx + x, cy + y);
		}
	}
	glEnd();
}

void BPainter::fillCircle(const BPointi& center, int radius, int sides) const
{
	fillCircle(center.x(), center.y(), radius, sides);
}
void BPainter::fillCircle(const BPointf& center, float radius, int sides) const
{
	fillCircle(center.x(), center.y(), radius, sides);
}
void BPainter::fillCircle(const BPointd& center, double radius, int sides) const
{
	fillCircle(center.x(), center.y(), radius, sides);
}

void BPainter::drawText(const BPointi& pos, const BString& text, Align align)
{
	drawText(pos.x(), pos.y(), text, align);
}
void BPainter::drawText(const BPointf& pos, const BString& text, Align align)
{
	drawText(pos.x(), pos.y(), text, align);
}
void BPainter::drawText(const BPointd& pos, const BString& text, Align align)
{
	drawText(pos.x(), pos.y(), text, align);
}

void BPainter::drawText(int x, int y, const BString& text, Align align)
{
	if (text.empty())
		return;

	const BFont* font = this->realFont();
	if (!font)
		return;

	if (align)
	{
		BSizei textSize = font->textSize(text);
		if (align & Align_Right)
			x -= textSize.width();
		if (align & Align_Bottom)
			y -= textSize.height();
		if (align & Align_HCenter)
			x -= textSize.width() / 2;
		if (align & Align_VCenter)
			y -= textSize.height() / 2;
	}

	unbind();
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	int fontHeight = font->size();
	int posX = x;
	int posY = (int)(y - fontHeight * 0.2);
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + member.clip.bottom())
			break;

		BSizei codeSize = font_member(font)->codeSize(*cit);

		if (cit == '\n')
		{
			posX = x;
			posY += fontHeight;
			continue;
		}
		if (cit == '\t')
		{
			int times = (posX - x) / codeSize.width() + 1;
			posX = times * codeSize.width() + x;
			continue;
		}
		CodeInfo* info = font_member(font)->getCodeInfo(*cit);
		if (info && info->image)
		{
			const BImage* image = info->image;
			int bx = posX + info->left;
			int by = posY + fontHeight - info->top;
			int bw = image->width();
			int bh = image->height();
			if (font_member(font)->monospace)
			{
				if (bw > codeSize.width())
				{
					bw = codeSize.width();
					bx = posX;
				}
				else
				{
					bx = posX + (codeSize.width() - bw) / 2;
				}
			}
			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(bx, by);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(bx, by + bh);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(bx + bw, by + bh);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(bx + bw, by);
			glEnd();
		}
		else
		{
			drawRect(posX, posY, codeSize.width(), codeSize.height());
		}
		posX += codeSize.width();
		if (posX > member.clip.right())
		{
			while (cit.valid() && *cit != '\n')
				++cit;
		}
	}
	glDisable(GL_TEXTURE_2D);
}
void BPainter::drawText(float x, float y, const BString& text, Align align)
{
	if (text.empty())
		return;

	const BFont* font = this->realFont();
	if (!font)
		return;

	if (align)
	{
		BSizei textSize = font->textSize(text);
		if (align & Align_Right)
			x -= textSize.width();
		if (align & Align_Bottom)
			y -= textSize.height();
		if (align & Align_HCenter)
			x -= textSize.width() / 2.0f;
		if (align & Align_VCenter)
			y -= textSize.height() / 2.0f;
	}

	unbind();
	glEnable(GL_TEXTURE_2D);

	int fontHeight = font->size();
	int posX = (int)x;
	int posY = (int)(y - fontHeight * 0.2f);
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + member.clip.bottom())
			break;
		BSize codeSize = font_member(font)->codeSize(*cit);
		if (cit == '\n')
		{
			posX = (int)x;
			posY += fontHeight;
			continue;
		}
		if (cit == '\t')
		{
			int times = int((posX - x) / codeSize.width() + 1);
			posX = times * codeSize.width() + (int)x;
			continue;
		}
		CodeInfo* info = font_member(font)->getCodeInfo(*cit);
		if (info && info->image)
		{
			const BImage* image = info->image;
			float bx = float(posX + info->left);
			float by = float(posY + fontHeight - info->top);
			float bw = (float)image->width();
			float bh = (float)image->height();
			if (font_member(font)->monospace)
			{
				if (bw > codeSize.width())
				{
					bw = (float)codeSize.width();
					bx = 0;
				}
				else
				{
					bx = posX + (codeSize.width() - bw) / 2;
				}
			}
			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2f(bx, by);
			glTexCoord2f(0.0f, 1.0f);		glVertex2f(bx, by + bh);
			glTexCoord2f(1.0f, 1.0f);		glVertex2f(bx + bw, by + bh);
			glTexCoord2f(1.0f, 0.0f);		glVertex2f(bx + bw, by);
			glEnd();
		}
		else
		{
			drawRect(posX, posY, codeSize.width(), codeSize.height());
		}
		posX += codeSize.width();
		if (posX > member.clip.right())
		{
			while (cit.valid() && *cit != '\n')
				++cit;
		}
	}
	glDisable(GL_TEXTURE_2D);
}
void BPainter::drawText(double x, double y, const BString& text, Align align)
{
	if (text.empty())
		return;

	const BFont* font = this->realFont();
	if (!font)
		return;

	if (align)
	{
		BSizei textSize = font->textSize(text);
		if (align & Align_Right)
			x -= textSize.width();
		if (align & Align_Bottom)
			y -= textSize.height();
		if (align & Align_HCenter)
			x -= textSize.width() / 2.0;
		if (align & Align_VCenter)
			y -= textSize.height() / 2.0;
	}

	unbind();
	glEnable(GL_TEXTURE_2D);

	int fontHeight = font->size();
	int posX = (int)x;
	int posY = (int)(y - fontHeight * 0.2);
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + member.clip.bottom())
			break;
		BSizei codeSize = font_member(font)->codeSize(*cit);
		if (cit == '\n')
		{
			posX = (int)x;
			posY += fontHeight;
			continue;
		}
		if (cit == '\t')
		{
			int times = int((posX - x) / codeSize.width() + 1);
			posX = times * codeSize.width() + (int)x;
			continue;
		}
		CodeInfo* info = font_member(font)->getCodeInfo(*cit);
		if (info && info->image)
		{
			const BImage* image = info->image;
			double bx = posX + info->left;
			double by = posY + fontHeight - info->top;
			double bw = image->width();
			double bh = image->height();
			if (font_member(font)->monospace)
			{
				if (bw > codeSize.width())
				{
					bw = codeSize.width();
					bx = posX;
				}
				else
				{
					bx = posX + (codeSize.width() - bw) / 2;
				}
			}
			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);		glVertex2d(bx, by);
			glTexCoord2d(0.0, 1.0);		glVertex2d(bx, by + bh);
			glTexCoord2d(1.0, 1.0);		glVertex2d(bx + bw, by + bh);
			glTexCoord2d(1.0, 0.0);		glVertex2d(bx + bw, by);
			glEnd();
		}
		else
		{
			drawRect(posX, posY, codeSize.width(), codeSize.height());
		}
		posX += codeSize.width();
		if (posX > member.clip.right())
		{
			while (cit.valid() && *cit != '\n')
				++cit;
		}
	}
	glDisable(GL_TEXTURE_2D);
}

void BPainter::drawText(const BRecti& rect, const BString& text, bool lineWrap)
{
	if (rect.empty() || text.empty())
		return;
	drawText(rect.x(), rect.y(), rect.width(), rect.height(), text, lineWrap);
}
void BPainter::drawText(const BRectf& rect, const BString& text, bool lineWrap)
{
	if (rect.empty() || text.empty())
		return;
	drawText(rect.x(), rect.y(), rect.width(), rect.height(), text, lineWrap);
}
void BPainter::drawText(const BRectd& rect, const BString& text, bool lineWrap)
{
	if (rect.empty() || text.empty())
		return;
	drawText(rect.x(), rect.y(), rect.width(), rect.height(), text, lineWrap);
}

void BPainter::drawText(const BPointi& pos, const BSizei& size, const BString& text, bool lineWrap)
{
	if (size.empty() || text.empty())
		return;
	drawText(pos.x(), pos.y(), size.width(), size.height(), text, lineWrap);
}
void BPainter::drawText(const BPointf& pos, const BSizef& size, const BString& text, bool lineWrap)
{
	if (size.empty() || text.empty())
		return;
	drawText(pos.x(), pos.y(), size.width(), size.height(), text, lineWrap);
}
void BPainter::drawText(const BPointd& pos, const BSized& size, const BString& text, bool lineWrap)
{
	if (size.empty() || text.empty())
		return;
	drawText(pos.x(), pos.y(), size.width(), size.height(), text, lineWrap);
}

void BPainter::drawText(int x, int y, int width, int height, const BString& text, bool lineWrap)
{
	if (text.empty())
		return;
	const BFont* font = this->realFont();
	if (!font)
		return;
	unbind();
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	int fontHeight = font->size();
	int posX = x;
	int posY = y - (int)(fontHeight * 0.2);
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + height)
			break;
		BSizei codeSize = font->codeSize(*cit);
		if (cit == '\n')
		{
			posX = x;
			posY += fontHeight;
			continue;
		}
		if (cit == '\t')
		{
			int times = (posX - x) / codeSize.width() + 1;
			posX = times * codeSize.width() + x;
			continue;
		}
		CodeInfo* info = font_member(font)->getCodeInfo(*cit);
		if (info && info->image)
		{
			const BImage* image = info->image;
			int bx = posX + info->left;
			int by = posY + fontHeight - info->top;
			int bw = image->width();
			int bh = image->height();
			if (font_member(font)->monospace)
			{
				if (bw > codeSize.width())
				{
					bw = codeSize.width();
					bx = posX;
				}
				else
				{
					bx = posX + (codeSize.width() - bw) / 2;
				}
			}
			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(bx, by);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(bx, by + bh);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(bx + bw, by + bh);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(bx + bw, by);
			glEnd();
		}
		if (posX + codeSize.width() > x + width)
		{
			if (!lineWrap)
			{
				while (cit.valid() && *cit != '\n')
					++cit;
			}
			posX = x;
			posY += fontHeight;
		}
		posX += codeSize.width();
	}
	glDisable(GL_TEXTURE_2D);
}
void BPainter::drawText(float x, float y, float width, float height, const BString& text, bool lineWrap)
{
	if (text.empty())
		return;
	const BFont* font = this->realFont();
	if (!font)
		return;
	unbind();
	glEnable(GL_TEXTURE_2D);
	float fontHeight = (float)font->size();
	float posX = x;
	float posY = y - fontHeight * 0.2f;
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + height)
			break;
		BSize codeSize = font->codeSize(*cit);
		if (cit == '\n')
		{
			posX = x;
			posY += fontHeight;
			continue;
		}
		if (cit == '\t')
		{
			int times = int(posX - x) / codeSize.width() + 1;
			posX = times * codeSize.width() + x;
			continue;
		}
		CodeInfo* info = font_member(font)->getLinearCodeInfo(*cit);
		if (info && info->image)
		{
			const BImage* image = info->image;
			float bx = posX + info->left;
			float by = posY + fontHeight - info->top;
			float bw = (float)image->width();
			float bh = (float)image->height();
			if (font_member(font)->monospace)
			{
				if (bw > codeSize.width())
				{
					bw = (float)codeSize.width();
					bx = 0;
				}
				else
				{
					bx = posX + (codeSize.width() - bw) / 2;
				}
			}
			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2f(bx, by);
			glTexCoord2f(0.0f, 1.0f);		glVertex2f(bx, by + bh);
			glTexCoord2f(1.0f, 1.0f);		glVertex2f(bx + bw, by + bh);
			glTexCoord2f(1.0f, 0.0f);		glVertex2f(bx + bw, by);
			glEnd();
		}
		if (posX + codeSize.width() > x + width)
		{
			if (!lineWrap)
			{
				while (cit.valid() && *cit != '\n')
					++cit;
			}
			posX = x;
			posY += fontHeight;
		}
		posX += codeSize.width();
	}
	glDisable(GL_TEXTURE_2D);
}
void BPainter::drawText(double x, double y, double width, double height, const BString& text, bool lineWrap)
{
	if (text.empty())
		return;
	const BFont* font = this->realFont();
	if (!font)
		return;
	unbind();
	glEnable(GL_TEXTURE_2D);
	double fontHeight = font->size();
	double posX = x;
	double posY = y - fontHeight * 0.2;
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + height)
			break;
		BSizei codeSize = font->codeSize(*cit);
		if (cit == '\n')
		{
			posX = x;
			posY += fontHeight;
			continue;
		}
		if (cit == '\t')
		{
			int times = int((posX - x) / codeSize.width()) + 1;
			posX = times * codeSize.width() + x;
			continue;
		}
		CodeInfo* info = font_member(font)->getLinearCodeInfo(*cit);
		if (info && info->image)
		{
			const BImage* image = info->image;
			double bx = posX + info->left;
			double by = posY + fontHeight - info->top;
			double bw = image->width();
			double bh = image->height();
			if (font_member(font)->monospace)
			{
				if (bw > codeSize.width())
				{
					bw = codeSize.width();
					bx = posX;
				}
				else
				{
					bx = posX + (codeSize.width() - bw) / 2;
				}
			}
			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2d(bx, by);
			glTexCoord2f(0.0f, 1.0f);		glVertex2d(bx, by + bh);
			glTexCoord2f(1.0f, 1.0f);		glVertex2d(bx + bw, by + bh);
			glTexCoord2f(1.0f, 0.0f);		glVertex2d(bx + bw, by);
			glEnd();
		}
		if (posX + codeSize.width() > x + width)
		{
			if (!lineWrap)
			{
				while (cit.valid() && *cit != '\n')
					++cit;
			}
			posX = x;
			posY += fontHeight;
		}
		posX += codeSize.width();
	}
	glDisable(GL_TEXTURE_2D);
}

void BPainter::drawText(const BRecti& rect, const BString& text, Align align, bool lineWrap)
{
	if (text.empty())
		return;
	const BFont* font = this->realFont();
	if (!font)
		return;
	BSizei textSize = font->textSize(text);
	BRecti textRect = rect.align(align, textSize);
	int fontHeight = font->size();
	int x = textRect.x();
	int y = textRect.y();
	unbind();
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	int pos = 0;
	BString line;
	while (pos < text.size())
	{
		pos = text.line(line, pos);
		int posX = x;
		int posY = y - (int)(fontHeight * 0.2);
		if (posY > y + fontHeight)
			break;
		for (BString::const_iterator cit = line.begin(); cit != line.end(); cit++)
		{
			BSizei codeSize = font_member(font)->codeSize(*cit);
			if (cit == '\t')
			{
				int times = (posX - x) / codeSize.width() + 1;
				posX = times * codeSize.width() + x;
				continue;
			}
			CodeInfo* info = font_member(font)->getCodeInfo(*cit);
			if (info && info->image)
			{
				const BImage* image = info->image;
				int bx = posX + info->left;
				int by = posY + fontHeight - info->top;
				int bw = image->width();
				int bh = image->height();
				if (font_member(font)->monospace)
				{
					if (bw > codeSize.width())
					{
						bw = codeSize.width();
						bx = posX;
					}
					else
					{
						bx = posX + (codeSize.width() - bw) / 2;
					}
				}
				if (texture_member(image)->dirty)
					image->flush();
				glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
				glBegin(GL_QUADS);
				glTexCoord2f(0.0f, 0.0f);		glVertex2i(bx, by);
				glTexCoord2f(0.0f, 1.0f);		glVertex2i(bx, by + bh);
				glTexCoord2f(1.0f, 1.0f);		glVertex2i(bx + bw, by + bh);
				glTexCoord2f(1.0f, 0.0f);		glVertex2i(bx + bw, by);
				glEnd();
			}
			if (posX + codeSize.width() > textRect.right())
			{
				break;
			}
			posX += codeSize.width();
		}
		y += fontHeight;
	}
	glDisable(GL_TEXTURE_2D);
}
void BPainter::drawText(const BRectf& rect, const BString& text, Align align, bool lineWrap)
{
	if (text.empty())
		return;
	const BFont* font = this->realFont();
	if (!font)
		return;
	BSizef textSize = font->textSize(text);
	BRectf textRect = rect.align(align, textSize);
	float fontHeight = (float)font->size();
	float x = textRect.x();
	float y = textRect.y();
	unbind();
	glEnable(GL_TEXTURE_2D);
	int pos = 0;
	BString line;
	while (pos < text.size())
	{
		pos = text.line(line, pos);
		float posX = x;
		float posY = y - fontHeight * 0.2f;
		if (posY > y + fontHeight)
			break;
		for (BString::const_iterator cit = line.begin(); cit != line.end(); cit++)
		{
			BSize codeSize = font->codeSize(*cit);
			if (cit == '\t')
			{
				int times = int((posX - x) / codeSize.width()) + 1;
				posX = times * codeSize.width() + x;
				continue;
			}
			CodeInfo* info = font_member(font)->getLinearCodeInfo(*cit);
			if (info && info->image)
			{
				const BImage* image = info->image;
				float bx = posX + info->left;
				float by = posY + fontHeight - info->top;
				float bw = (float)image->width();
				float bh = (float)image->height();
				if (font_member(font)->monospace)
				{
					if (bw > codeSize.width())
					{
						bw = (float)codeSize.width();
						bx = 0;
					}
					else
					{
						bx = posX + (codeSize.width() - bw) / 2;
					}
				}
				if (texture_member(image)->dirty)
					image->flush();
				glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
				glBegin(GL_QUADS);
				glTexCoord2f(0.0f, 0.0f);		glVertex2f(bx, by);
				glTexCoord2f(0.0f, 1.0f);		glVertex2f(bx, by + bh);
				glTexCoord2f(1.0f, 1.0f);		glVertex2f(bx + bw, by + bh);
				glTexCoord2f(1.0f, 0.0f);		glVertex2f(bx + bw, by);
				glEnd();
			}
			if (posX + codeSize.width() > textRect.right())
			{
				break;
			}
			posX += codeSize.width();
		}
		y += fontHeight;
	}
	glDisable(GL_TEXTURE_2D);
}
void BPainter::drawText(const BRectd& rect, const BString& text, Align align, bool lineWrap)
{
	if (text.empty())
		return;
	const BFont* font = this->realFont();
	if (!font)
		return;
	BSized textSize = font->textSize(text);
	BRectd textRect = rect.align(align, textSize);
	double fontHeight = font->size();
	double x = textRect.x();
	double y = textRect.y();
	unbind();
	glEnable(GL_TEXTURE_2D);
	int pos = 0;
	BString line;
	while (pos < text.size())
	{
		pos = text.line(line, pos);
		double posX = x;
		double posY = y - fontHeight * 0.2f;
		if (posY > y + fontHeight)
			break;
		for (BString::const_iterator cit = line.begin(); cit != line.end(); cit++)
		{
			BSizei codeSize = font->codeSize(*cit);
			if (cit == '\t')
			{
				int times = int((posX - x) / codeSize.width()) + 1;
				posX = times * codeSize.width() + x;
				continue;
			}
			CodeInfo* info = font_member(font)->getLinearCodeInfo(*cit);
			if (info && info->image)
			{
				const BImage* image = info->image;
				double bx = posX + info->left;
				double by = posY + fontHeight - info->top;
				double bw = image->width();
				double bh = image->height();
				if (font_member(font)->monospace)
				{
					if (bw > codeSize.width())
					{
						bw = codeSize.width();
						bx = posX;
					}
					else
					{
						bx = posX + (codeSize.width() - bw) / 2;
					}
				}
				if (texture_member(image)->dirty)
					image->flush();
				glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
				glBegin(GL_QUADS);
				glTexCoord2f(0.0f, 0.0f);		glVertex2d(bx, by);
				glTexCoord2f(0.0f, 1.0f);		glVertex2d(bx, by + bh);
				glTexCoord2f(1.0f, 1.0f);		glVertex2d(bx + bw, by + bh);
				glTexCoord2f(1.0f, 0.0f);		glVertex2d(bx + bw, by);
				glEnd();
			}
			if (posX + codeSize.width() > textRect.right())
			{
				break;
			}
			posX += codeSize.width();
		}
		y += fontHeight;
	}
	glDisable(GL_TEXTURE_2D);
}

void BPainter::drawText(const BPointi& pos, const BSizei& size, const BString& text, Align align, bool lineWrap)
{
	drawText(BRecti(pos, size), text, align, lineWrap);
}
void BPainter::drawText(const BPointf& pos, const BSizef& size, const BString& text, Align align, bool lineWrap)
{
	drawText(BRectf(pos, size), text, align, lineWrap);
}
void BPainter::drawText(const BPointd& pos, const BSized& size, const BString& text, Align align, bool lineWrap)
{
	drawText(BRectd(pos, size), text, align, lineWrap);
}

void BPainter::drawText(int x, int y, int width, int height, const BString& text, Align align, bool lineWrap)
{
	drawText(BRecti(x, y, width, height), text, align, lineWrap);
}
void BPainter::drawText(float x, float y, float width, float height, const BString& text, Align align, bool lineWrap)
{
	drawText(BRectf(x, y, width, height), text, align, lineWrap);
}
void BPainter::drawText(double x, double y, double width, double height, const BString& text, Align align, bool lineWrap)
{
	drawText(BRectd(x, y, width, height), text, align, lineWrap);
}

void BPainter::drawImage(const BPointi& pos, const BImage* image, Align align)
{
	drawImage(pos.x(), pos.y(), image, align);
}
void BPainter::drawImage(const BPointf& pos, const BImage* image, Align align)
{
	drawImage(pos.x(), pos.y(), image, align);
}
void BPainter::drawImage(const BPointd& pos, const BImage* image, Align align)
{
	drawImage(pos.x(), pos.y(), image, align);
}

void BPainter::drawImage(int x, int y, const BImage* image, Align align)
{
	if (!image)
		return;
	BSizei size = image->size();
	if (align)
	{
		if (align & Align_Right)
			x -= size.width();
		if (align & Align_Bottom)
			y -= size.height();
		if (align & Align_HCenter)
			x -= size.width() / 2;
		if (align & Align_VCenter)
			y -= size.height() / 2;
	}
	drawImage(x, y, size.width(), size.height(), image, false);
}
void BPainter::drawImage(float x, float y, const BImage* image, Align align)
{
	if (!image)
		return;
	BSizef size = image->size();
	if (align)
	{
		if (align & Align_Right)
			x -= size.width();
		if (align & Align_Bottom)
			y -= size.height();
		if (align & Align_HCenter)
			x -= size.width() / 2.0f;
		if (align & Align_VCenter)
			y -= size.height() / 2.0f;
	}
	drawImage(x, y, size.width(), size.height(), image, false);
}
void BPainter::drawImage(double x, double y, const BImage* image, Align align)
{
	if (!image)
		return;
	BSized size = image->size();
	if (align)
	{
		if (align & Align_Right)
			x -= size.width();
		if (align & Align_Bottom)
			y -= size.height();
		if (align & Align_HCenter)
			x -= size.width() / 2.0;
		if (align & Align_VCenter)
			y -= size.height() / 2.0;
	}
	drawImage(x, y, size.width(), size.height(), image, false);
}

void BPainter::drawImage(const BRecti& rect, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSizei imageSize = rect.size().wrap(image->size());
			BRecti imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(imageRect.left(), imageRect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(imageRect.left(), imageRect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(imageRect.right(), imageRect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(imageRect.right(), imageRect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(rect.left(), rect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(rect.left(), rect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(rect.right(), rect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(rect.right(), rect.top());
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(const BRectf& rect, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSizef imageSize = rect.size().wrap(image->size());
			BRectf imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2f(imageRect.left(), imageRect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2f(imageRect.left(), imageRect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2f(imageRect.right(), imageRect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2f(imageRect.right(), imageRect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2f(rect.left(), rect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2f(rect.left(), rect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2f(rect.right(), rect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2f(rect.right(), rect.top());
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(const BRectd& rect, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSized imageSize = rect.size().wrap(image->size());
			BRectd imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);		glVertex2d(imageRect.left(), imageRect.top());
			glTexCoord2d(0.0, 1.0);		glVertex2d(imageRect.left(), imageRect.bottom());
			glTexCoord2d(1.0, 1.0);		glVertex2d(imageRect.right(), imageRect.bottom());
			glTexCoord2d(1.0, 0.0);		glVertex2d(imageRect.right(), imageRect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);		glVertex2d(rect.left(), rect.top());
			glTexCoord2d(0.0, 1.0);		glVertex2d(rect.left(), rect.bottom());
			glTexCoord2d(1.0, 1.0);		glVertex2d(rect.right(), rect.bottom());
			glTexCoord2d(1.0, 0.0);		glVertex2d(rect.right(), rect.top());
			glEnd();
		}
		unbind();
	}
}

void BPainter::drawImage(const BPointi& pos, const BSizei& size, const BImage* image, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, wrapped);
}
void BPainter::drawImage(const BPointf& pos, const BSizef& size, const BImage* image, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, wrapped);
}
void BPainter::drawImage(const BPointd& pos, const BSized& size, const BImage* image, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, wrapped);
}

void BPainter::drawImage(int x, int y, int width, int height, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSizei imageSize = BSizei(width, height).wrap(image->size());
			BRecti rect = BRecti(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(rect.left(), rect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(rect.left(), rect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(rect.right(), rect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(rect.right(), rect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(x, y);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(x, y + height);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(x + width, y + height);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(x + width, y);
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(float x, float y, float width, float height, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSizef imageSize = BSizef(width, height).wrap(image->size());
			BRectf rect = BRectf(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2f(rect.left(), rect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2f(rect.left(), rect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2f(rect.right(), rect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2f(rect.right(), rect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2f(x, y);
			glTexCoord2f(0.0f, 1.0f);		glVertex2f(x, y + height);
			glTexCoord2f(1.0f, 1.0f);		glVertex2f(x + width, y + height);
			glTexCoord2f(1.0f, 0.0f);		glVertex2f(x + width, y);
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(double x, double y, double width, double height, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSized imageSize = BSized(width, height).wrap(image->size());
			BRectd rect = BRectd(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);		glVertex2d(rect.left(), rect.top());
			glTexCoord2d(0.0, 1.0);		glVertex2d(rect.left(), rect.bottom());
			glTexCoord2d(1.0, 1.0);		glVertex2d(rect.right(), rect.bottom());
			glTexCoord2d(1.0, 0.0);		glVertex2d(rect.right(), rect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2d(0.0, 0.0);		glVertex2d(x, y);
			glTexCoord2d(0.0, 1.0);		glVertex2d(x, y + height);
			glTexCoord2d(1.0, 1.0);		glVertex2d(x + width, y + height);
			glTexCoord2d(1.0, 0.0);		glVertex2d(x + width, y);
			glEnd();
		}
		unbind();
	}
}

void BPainter::drawImage(const BRecti& rect, const BImage* image, Align align, bool wrapped)
{
	if (bind(image))
	{
		BSizei imageSize = image->size();
		if (wrapped)
		{
			imageSize = rect.size().wrap(imageSize);
		}
		BRect imageRect = rect;
		if (align)
		{
			imageRect = rect.align(align, imageSize);
		}
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f);		glVertex2i(imageRect.left(), imageRect.top());
		glTexCoord2f(0.0f, 1.0f);		glVertex2i(imageRect.left(), imageRect.bottom());
		glTexCoord2f(1.0f, 1.0f);		glVertex2i(imageRect.right(), imageRect.bottom());
		glTexCoord2f(1.0f, 0.0f);		glVertex2i(imageRect.right(), imageRect.top());
		glEnd();
		unbind();
	}
}
void BPainter::drawImage(const BRectf& rect, const BImage* image, Align align, bool wrapped)
{
	if (bind(image))
	{
		BSizef imageSize = image->size();
		if (wrapped)
		{
			imageSize = rect.size().wrap(imageSize);
		}
		BRectf imageRect = rect;
		if (align)
		{
			imageRect = rect.align(align, imageSize);
		}
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f);		glVertex2f(imageRect.left(), imageRect.top());
		glTexCoord2f(0.0f, 1.0f);		glVertex2f(imageRect.left(), imageRect.bottom());
		glTexCoord2f(1.0f, 1.0f);		glVertex2f(imageRect.right(), imageRect.bottom());
		glTexCoord2f(1.0f, 0.0f);		glVertex2f(imageRect.right(), imageRect.top());
		glEnd();
		unbind();
	}
}
void BPainter::drawImage(const BRectd& rect, const BImage* image, Align align, bool wrapped)
{
	if (bind(image))
	{
		BSized imageSize = image->size();
		if (wrapped)
		{
			imageSize = rect.size().wrap(imageSize);
		}
		BRectd imageRect = rect;
		if (align)
		{
			imageRect = rect.align(align, imageSize);
		}
		glBegin(GL_QUADS);
		glTexCoord2d(0.0, 0.0);		glVertex2d(imageRect.left(), imageRect.top());
		glTexCoord2d(0.0, 1.0);		glVertex2d(imageRect.left(), imageRect.bottom());
		glTexCoord2d(1.0, 1.0);		glVertex2d(imageRect.right(), imageRect.bottom());
		glTexCoord2d(1.0, 0.0);		glVertex2d(imageRect.right(), imageRect.top());
		glEnd();
		unbind();
	}
}

void BPainter::drawImage(const BPointi& pos, const BSizei& size, const BImage* image, Align align, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, align, wrapped);
}
void BPainter::drawImage(const BPointf& pos, const BSizef& size, const BImage* image, Align align, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, align, wrapped);
}
void BPainter::drawImage(const BPointd& pos, const BSized& size, const BImage* image, Align align, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, align, wrapped);
}

void BPainter::drawImage(int x, int y, int width, int height, const BImage* image, Align align, bool wrapped)
{
	drawImage(BRecti(x, y, width, height), image, align, wrapped);
}
void BPainter::drawImage(float x, float y, float width, float height, const BImage* image, Align align, bool wrapped)
{
	drawImage(BRectf(x, y, width, height), image, align, wrapped);
}
void BPainter::drawImage(double x, double y, double width, double height, const BImage* image, Align align, bool wrapped)
{
	drawImage(BRectd(x, y, width, height), image, align, wrapped);
}

void BPainter::drawImage(const BRecti& rect, const BImage* image, const BRecti& area, bool wrapped)
{
	if (bind(image))
	{
		float rw = 1.0f / image->width();
		float rh = 1.0f / image->height();
		float tx0 = area.left() * rw;
		float tx1 = area.right() * rw;
		float ty0 = area.top() * rh;
		float ty1 = area.bottom() * rh;
		if (wrapped)
		{
			BSizei imageSize = rect.size().wrap(area.size());
			BRecti imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(tx0, ty0);		glVertex2i(imageRect.x(), imageRect.y());
			glTexCoord2f(tx0, ty1);		glVertex2i(imageRect.x(), imageRect.y() + imageRect.height());
			glTexCoord2f(tx1, ty1);		glVertex2i(imageRect.x() + imageRect.width(), imageRect.y() + imageRect.height());
			glTexCoord2f(tx1, ty0);		glVertex2i(imageRect.x() + imageRect.width(), imageRect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(tx0, ty0);		glVertex2i(rect.x(), rect.y());
			glTexCoord2f(tx0, ty1);		glVertex2i(rect.x(), rect.y() + rect.height());
			glTexCoord2f(tx1, ty1);		glVertex2i(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2f(tx1, ty0);		glVertex2i(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(const BRectf& rect, const BImage* image, const BRectf& area, bool wrapped)
{
	if (bind(image))
	{
		float rw = 1.0f / image->width();
		float rh = 1.0f / image->height();
		float tx0 = area.left() * rw;
		float tx1 = area.right() * rw;
		float ty0 = area.top() * rh;
		float ty1 = area.bottom() * rh;
		if (wrapped)
		{
			BSizef imageSize = rect.size().wrap(area.size());
			BRectf imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(tx0, ty0);		glVertex2f(imageRect.x(), imageRect.y());
			glTexCoord2f(tx0, ty1);		glVertex2f(imageRect.x(), imageRect.y() + imageRect.height());
			glTexCoord2f(tx1, ty1);		glVertex2f(imageRect.x() + imageRect.width(), imageRect.y() + imageRect.height());
			glTexCoord2f(tx1, ty0);		glVertex2f(imageRect.x() + imageRect.width(), imageRect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(tx0, ty0);		glVertex2f(rect.x(), rect.y());
			glTexCoord2f(tx0, ty1);		glVertex2f(rect.x(), rect.y() + rect.height());
			glTexCoord2f(tx1, ty1);		glVertex2f(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2f(tx1, ty0);		glVertex2f(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(const BRectd& rect, const BImage* image, const BRectd& area, bool wrapped)
{
	if (bind(image))
	{
		double rw = 1.0 / image->width();
		double rh = 1.0 / image->height();
		double tx0 = area.left() * rw;
		double tx1 = area.right() * rw;
		double ty0 = area.top() * rh;
		double ty1 = area.bottom() * rh;
		if (wrapped)
		{
			BSized imageSize = rect.size().wrap(area.size());
			BRectd imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2d(tx0, ty0);		glVertex2d(imageRect.x(), imageRect.y());
			glTexCoord2d(tx0, ty1);		glVertex2d(imageRect.x(), imageRect.y() + imageRect.height());
			glTexCoord2d(tx1, ty1);		glVertex2d(imageRect.x() + imageRect.width(), imageRect.y() + imageRect.height());
			glTexCoord2d(tx1, ty0);		glVertex2d(imageRect.x() + imageRect.width(), imageRect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2d(tx0, ty0);		glVertex2d(rect.x(), rect.y());
			glTexCoord2d(tx0, ty1);		glVertex2d(rect.x(), rect.y() + rect.height());
			glTexCoord2d(tx1, ty1);		glVertex2d(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2d(tx1, ty0);		glVertex2d(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		unbind();
	}
}

void BPainter::drawImage(const BPointi& pos, const BSizei& size, const BImage* image, const BRecti& area, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, area, wrapped);
}
void BPainter::drawImage(const BPointf& pos, const BSizef& size, const BImage* image, const BRectf& area, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, area, wrapped);
}
void BPainter::drawImage(const BPointd& pos, const BSized& size, const BImage* image, const BRectd& area, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, area, wrapped);
}

void BPainter::drawImage(int x, int y, int width, int height, const BImage* image, const BRecti& area, bool wrapped)
{
	if (bind(image))
	{
		float rw = 1.0f / area.width();
		float rh = 1.0f / area.height();
		if (wrapped)
		{
			BSizei imageSize = BSizei(width, height).wrap(image->size());
			BRecti rect = BRecti(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(area.left() * rw, area.top() * rh);		glVertex2i(rect.x(), rect.y());
			glTexCoord2f(area.left() * rw, area.bottom() * rh);		glVertex2i(rect.x(), rect.y() + rect.height());
			glTexCoord2f(area.right() * rw, area.bottom() * rh);	glVertex2i(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2f(area.right() * rw, area.top() * rh);		glVertex2i(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(area.left() * rw, area.top() * rh);		glVertex2i(x, y);
			glTexCoord2f(area.left() * rw, area.bottom() * rh);		glVertex2i(x, y + height);
			glTexCoord2f(area.right() * rw, area.bottom() * rh);	glVertex2i(x + width, y + height);
			glTexCoord2f(area.right() * rw, area.top() * rh);		glVertex2i(x + width, y);
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(float x, float y, float width, float height, const BImage* image, const BRectf& area, bool wrapped)
{
	if (bind(image))
	{
		float rw = 1.0f / area.width();
		float rh = 1.0f / area.height();
		if (wrapped)
		{
			BSizef imageSize = BSizef(width, height).wrap(image->size());
			BRectf rect = BRecti(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(area.left() * rw, area.top() * rh);		glVertex2f(rect.x(), rect.y());
			glTexCoord2f(area.left() * rw, area.bottom() * rh);		glVertex2f(rect.x(), rect.y() + rect.height());
			glTexCoord2f(area.right() * rw, area.bottom() * rh);	glVertex2f(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2f(area.right() * rw, area.top() * rh);		glVertex2f(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(area.left() * rw, area.top() * rh);		glVertex2f(x, y);
			glTexCoord2f(area.left() * rw, area.bottom() * rh);		glVertex2f(x, y + height);
			glTexCoord2f(area.right() * rw, area.bottom() * rh);	glVertex2f(x + width, y + height);
			glTexCoord2f(area.right() * rw, area.top() * rh);		glVertex2f(x + width, y);
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(double x, double y, double width, double height, const BImage* image, const BRectd& area, bool wrapped)
{
	if (bind(image))
	{
		double rw = 1.0 / area.width();
		double rh = 1.0 / area.height();
		if (wrapped)
		{
			BSized imageSize = BSized(width, height).wrap(image->size());
			BRectd rect = BRectd(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2d(area.left() * rw, area.top() * rh);		glVertex2d(rect.x(), rect.y());
			glTexCoord2d(area.left() * rw, area.bottom() * rh);		glVertex2d(rect.x(), rect.y() + rect.height());
			glTexCoord2d(area.right() * rw, area.bottom() * rh);	glVertex2d(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2d(area.right() * rw, area.top() * rh);		glVertex2d(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2d(area.left() * rw, area.top() * rh);		glVertex2d(x, y);
			glTexCoord2d(area.left() * rw, area.bottom() * rh);		glVertex2d(x, y + height);
			glTexCoord2d(area.right() * rw, area.bottom() * rh);	glVertex2d(x + width, y + height);
			glTexCoord2d(area.right() * rw, area.top() * rh);		glVertex2d(x + width, y);
			glEnd();
		}
		unbind();
	}
}

void BPainter::drawImage(const BRecti& rect, const BImage* image, const BMargini& margin)
{
	if (bind(image))
	{
		int top = margin.top();
		int left = margin.left();
		int right = margin.right();
		int bottom = margin.bottom();

		BRecti crect = rect;
		crect.top() += top;
		crect.left() += left;
		crect.right() -= right;
		crect.bottom() -= bottom;

		int tw = member.tsize.width();
		int th = member.tsize.height();

		fillRect(rect.left(), crect.top(), left, crect.height(), BRecti(0, top, left, th - top - bottom));
		fillRect(crect.left(), rect.top(), crect.width(), top, BRecti(left, 0, tw - left - right, top));
		fillRect(crect.right(), crect.top(), right, crect.height(), BRecti(tw - left, top, right, th - top - bottom));
		fillRect(crect.left(), crect.bottom(), crect.width(), bottom, BRecti(left, th - bottom, tw - left - right, bottom));

		fillRect(rect.left(), rect.top(), left, top, BRecti(0, 0, left, top));
		fillRect(crect.right(), rect.top(), right, top, BRecti(tw - right, 0, right, top));
		fillRect(rect.left(), crect.bottom(), left, bottom, BRecti(0, th - bottom, left, bottom));
		fillRect(crect.right(), crect.bottom(), right, bottom, BRecti(tw - right, th - bottom, right, bottom));

		fillRect(crect, BRecti(left, top, tw - left - right, th - top - bottom));

		unbind();
	}
}
void BPainter::drawImage(const BRectf& rect, const BImage* image, const BMarginf& margin)
{
	if (bind(image))
	{
		float top = margin.top();
		float left = margin.left();
		float right = margin.right();
		float bottom = margin.bottom();

		BRectf crect = rect;
		crect.top() += top;
		crect.left() += left;
		crect.right() -= right;
		crect.bottom() -= bottom;

		int tw = member.tsize.width();
		int th = member.tsize.height();

		fillRect(rect.left(), crect.top(), left, crect.height(), BRectf(0, top, left, th - top - bottom));
		fillRect(crect.left(), rect.top(), crect.width(), top, BRectf(left, 0, tw - left - right, top));
		fillRect(crect.right(), crect.top(), right, crect.height(), BRectf(tw - left, top, right, th - top - bottom));
		fillRect(crect.left(), crect.bottom(), crect.width(), bottom, BRectf(left, th - bottom, tw - left - right, bottom));

		fillRect(rect.left(), rect.top(), left, top, BRectf(0, 0, left, top));
		fillRect(crect.right(), rect.top(), right, top, BRectf(tw - right, 0, right, top));
		fillRect(rect.left(), crect.bottom(), left, bottom, BRectf(0, th - bottom, left, bottom));
		fillRect(crect.right(), crect.bottom(), right, bottom, BRectf(tw - right, th - bottom, right, bottom));

		fillRect(crect, BRectf(left, top, tw - left - right, th - top - bottom));

		unbind();
	}
}
void BPainter::drawImage(const BRectd& rect, const BImage* image, const BMargind& margin)
{
	if (bind(image))
	{
		double top = margin.top();
		double left = margin.left();
		double right = margin.right();
		double bottom = margin.bottom();

		BRectd crect = rect;
		crect.top() += top;
		crect.left() += left;
		crect.right() -= right;
		crect.bottom() -= bottom;

		int tw = member.tsize.width();
		int th = member.tsize.height();

		fillRect(rect.left(), crect.top(), left, crect.height(), BRectd(0, top, left, th - top - bottom));
		fillRect(crect.left(), rect.top(), crect.width(), top, BRectd(left, 0, tw - left - right, top));
		fillRect(crect.right(), crect.top(), right, crect.height(), BRectd(tw - left, top, right, th - top - bottom));
		fillRect(crect.left(), crect.bottom(), crect.width(), bottom, BRectd(left, th - bottom, tw - left - right, bottom));

		fillRect(rect.left(), rect.top(), left, top, BRectd(0, 0, left, top));
		fillRect(crect.right(), rect.top(), right, top, BRectd(tw - right, 0, right, top));
		fillRect(rect.left(), crect.bottom(), left, bottom, BRectd(0, th - bottom, left, bottom));
		fillRect(crect.right(), crect.bottom(), right, bottom, BRectd(tw - right, th - bottom, right, bottom));

		fillRect(crect, BRectd(left, top, tw - left - right, th - top - bottom));

		unbind();
	}
}

void BPainter::drawImage(const BPointi& pos, const BSizei& size, const BImage* image, const BMargini& margin)
{
	drawImage(BRecti(pos, size), image, margin);
}
void BPainter::drawImage(const BPointf& pos, const BSizef& size, const BImage* image, const BMarginf& margin)
{
	drawImage(BRectf(pos, size), image, margin);
}
void BPainter::drawImage(const BPointd& pos, const BSized& size, const BImage* image, const BMargind& margin)
{
	drawImage(BRectd(pos, size), image, margin);
}

void BPainter::drawImage(int x, int y, int width, int height, const BImage* image, const BMargini& margin)
{
	drawImage(BRecti(x, y, width, height), image, margin);
}
void BPainter::drawImage(float x, float y, float width, float height, const BImage* image, const BMarginf& margin)
{
	drawImage(BRectf(x, y, width, height), image, margin);
}
void BPainter::drawImage(double x, double y, double width, double height, const BImage* image, const BMargind& margin)
{
	drawImage(BRectd(x, y, width, height), image, margin);
}

void BPainter::tileImage(const BRecti& rect, const BImage* image)
{
	if (bind(image))
	{
		float tx = (float)rect.width() / image->width();
		float ty = (float)rect.height() / image->height();
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f);		glVertex2i(rect.left(), rect.top());
		glTexCoord2f(0.0f, ty);			glVertex2i(rect.left(), rect.bottom());
		glTexCoord2f(tx, ty);			glVertex2i(rect.right(), rect.bottom());
		glTexCoord2f(tx, 0.0f);			glVertex2i(rect.right(), rect.top());
		glEnd();
		unbind();
	}
}
void BPainter::tileImage(const BRectf& rect, const BImage* image)
{
	if (bind(image))
	{
		float tx = rect.width() / image->width();
		float ty = rect.height() / image->height();
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f);		glVertex2f(rect.left(), rect.top());
		glTexCoord2f(0.0f, ty);			glVertex2f(rect.left(), rect.bottom());
		glTexCoord2f(tx, ty);			glVertex2f(rect.right(), rect.bottom());
		glTexCoord2f(tx, 0.0f);			glVertex2f(rect.right(), rect.top());
		glEnd();
		unbind();
	}
}
void BPainter::tileImage(const BRectd& rect, const BImage* image)
{
	if (bind(image))
	{
		double tx = rect.width() / image->width();
		double ty = rect.height() / image->height();
		glBegin(GL_QUADS);
		glTexCoord2d(0.0, 0.0);		glVertex2d(rect.left(), rect.top());
		glTexCoord2d(0.0, ty);		glVertex2d(rect.left(), rect.bottom());
		glTexCoord2d(tx, ty);		glVertex2d(rect.right(), rect.bottom());
		glTexCoord2d(tx, 0.0);		glVertex2d(rect.right(), rect.top());
		glEnd();
		unbind();
	}
}

void BPainter::tileImage(const BPointi& pos, const BSizei& size, const BImage* image)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image);
}
void BPainter::tileImage(const BPointf& pos, const BSizef& size, const BImage* image)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image);
}
void BPainter::tileImage(const BPointd& pos, const BSized& size, const BImage* image)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image);
}

void BPainter::tileImage(int x, int y, int width, int height, const BImage* image)
{
	if (bind(image))
	{
		float tx = (float)width / image->width();
		float ty = (float)height / image->height();
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f);		glVertex2i(x, y);
		glTexCoord2f(0.0f, ty);			glVertex2i(x, y + height);
		glTexCoord2f(tx, ty);			glVertex2i(x + width, y + height);
		glTexCoord2f(tx, 0.0f);			glVertex2i(x + width, y);
		glEnd();
		unbind();
	}
}
void BPainter::tileImage(float x, float y, float width, float height, const BImage* image)
{
	if (bind(image))
	{
		float tx = width / image->width();
		float ty = height / image->height();
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f);		glVertex2f(x, y);
		glTexCoord2f(0.0f, ty);			glVertex2f(x, y + height);
		glTexCoord2f(tx, ty);			glVertex2f(x + width, y + height);
		glTexCoord2f(tx, 0.0f);			glVertex2f(x + width, y);
		glEnd();
		unbind();
	}
}
void BPainter::tileImage(double x, double y, double width, double height, const BImage* image)
{
	if (bind(image))
	{
		double tx = width / image->width();
		double ty = height / image->height();
		glBegin(GL_QUADS);
		glTexCoord2d(0.0, 0.0);		glVertex2d(x, y);
		glTexCoord2d(0.0, ty);		glVertex2d(x, y + height);
		glTexCoord2d(tx, ty);		glVertex2d(x + width, y + height);
		glTexCoord2d(tx, 0.0);		glVertex2d(x + width, y);
		glEnd();
		unbind();
	}
}

void BPainter::drawGraph(int x, int y, int width, int height, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		drawGraph(BRecti(x, y, width, height), graph);
	}
}
void BPainter::drawGraph(float x, float y, float width, float height, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		drawGraph(BRectf(x, y, width, height), graph);
	}
}
void BPainter::drawGraph(double x, double y, double width, double height, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		drawGraph(BRectd(x, y, width, height), graph);
	}
}

void BPainter::drawGraph(const BPointi& pos, const BSizei& size, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		drawGraph(BRecti(pos, size), graph);
	}
}
void BPainter::drawGraph(const BPointf& pos, const BSizef& size, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		drawGraph(BRectf(pos, size), graph);
	}
}
void BPainter::drawGraph(const BPointd& pos, const BSized& size, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		drawGraph(BRectd(pos, size), graph);
	}
}

void BPainter::drawGraph(const BRecti& rect, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		float x = (float)rect.x();
		float y = (float)rect.y();
		float w = (float)rect.width();
		float h = (float)rect.height();
		switch (graph)
		{
		case Graph_Circle:
		{
			int radius = bMin(rect.width(), rect.height());
			glEnable(GL_LINE_SMOOTH);
			drawCircle(rect.center(), radius / 2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Circle_Fill:
		{
			int radius = bMin(rect.width(), rect.height());
			glEnable(GL_MULTISAMPLE);
			fillCircle(rect.center(), radius / 2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Square:
		{
			drawRect(rect);
			break;
		}
		case Graph_Square_Fill:
		{
			fillRect(rect);
			break;
		}
		case Graph_Round:
		{
			glEnable(GL_LINE_SMOOTH);
			drawRoundRect(rect, rect.width() / 3, rect.height() / 3);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Round_Fill:
		{
			glEnable(GL_MULTISAMPLE);
			fillRoundRect(rect, rect.width() / 3, rect.height() / 3);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Up:
		{
			BPointf p1(x + w / 2, y);
			BPointf p0(x, y + h);
			BPointf p2(x + w, y + h);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Down:
		{
			BPointf p0(x, y);
			BPointf p1(x + w / 2, y + h);
			BPointf p2(x + w, y);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Left:
		{
			BPointf p0(x + w, y);
			BPointf p1(x, y + h / 2);
			BPointf p2(x + w, y + h);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Right:
		{
			BPointf p0(x, y);
			BPointf p1(x, y + h);
			BPointf p2(x + w, y + h / 2);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Up_Fill:
		{
			BPointf p1(x + w / 2, y);
			BPointf p0(x, y + h);
			BPointf p2(x + w, y + h);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Down_Fill:
		{
			BPointf p0(x, y);
			BPointf p1(x + w / 2, y + h);
			BPointf p2(x + w, y);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Left_Fill:
		{
			BPointf p0(x, y + h / 2);
			BPointf p1(x + w, y + h);
			BPointf p2(x + w, y);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Right_Fill:
		{
			BPointf p0(x, y);
			BPointf p1(x, y + h);
			BPointf p2(x + w, y + h / 2);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftTop:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightTop:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.rightBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftBottom:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightBottom:
		{
			BPointf p0 = rect.rightTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftTop_Fill:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightTop_Fill:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.rightBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftBottom_Fill:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightBottom_Fill:
		{
			BPointf p0 = rect.rightTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Minus:
		{
			BPointf p0(x, y + h / 2);
			BPointf p1(x + w, y + h / 2);
			drawLine(p0, p1);
			break;
		}
		case Graph_Plus:
		{
			BPointf p1(x + w / 2, y);
			BPointf p0(x + w / 2, y + h);
			BPointf p2(x, y + h / 2);
			BPointf p3(x + w, y + h / 2);
			drawLine(p0, p1);
			drawLine(p2, p3);
			break;
		}
		case Graph_Cross:
		{
			glEnable(GL_LINE_SMOOTH);
			drawLine(rect.leftTop(), rect.rightBottom());
			drawLine(rect.leftBottom(), rect.rightTop());
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Minimize:
		{
			BRecti minRect = rect % 50;
			drawLine(minRect.leftBottom(), minRect.rightBottom());
			break;
		}
		case Graph_Maximize:
		{
			BRecti maxRect = rect % 60;
			drawRect(maxRect);
			break;
		}
		case Graph_Normalize:
		{
			BRecti maxRect = rect % 50;
			drawRect(maxRect);
			break;
		}
		default:
			break;
		}
	}
}
void BPainter::drawGraph(const BRectf& rect, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		float x = rect.x();
		float y = rect.y();
		float w = rect.width();
		float h = rect.height();
		switch (graph)
		{
		case Graph_Circle:
		{
			float radius = bMin(rect.width(), rect.height());
			glEnable(GL_LINE_SMOOTH);
			drawCircle(rect.center(), radius / 2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Circle_Fill:
		{
			float radius = bMin(rect.width(), rect.height());
			glEnable(GL_MULTISAMPLE);
			fillCircle(rect.center(), radius / 2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Square:
		{
			drawRect(rect);
			break;
		}
		case Graph_Square_Fill:
		{
			fillRect(rect);
			break;
		}
		case Graph_Round:
		{
			glEnable(GL_LINE_SMOOTH);
			drawRoundRect(rect, rect.width() / 3, rect.height() / 3);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Round_Fill:
		{
			glEnable(GL_MULTISAMPLE);
			fillRoundRect(rect, rect.width() / 3, rect.height() / 3);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Up:
		{
			BPointf p1(x + w / 2, y);
			BPointf p0(x, y + h);
			BPointf p2(x + w, y + h);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Down:
		{
			BPointf p0(x, y);
			BPointf p1(x + w / 2, y + h);
			BPointf p2(x + w, y);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Left:
		{
			BPointf p0(x + w, y);
			BPointf p1(x, y + h / 2);
			BPointf p2(x + w, y + h);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Right:
		{
			BPointf p0(x, y);
			BPointf p1(x, y + h);
			BPointf p2(x + w, y + h / 2);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Up_Fill:
		{
			BPointf p1(x + w / 2, y);
			BPointf p0(x, y + h);
			BPointf p2(x + w, y + h);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Down_Fill:
		{
			BPointf p0(x, y);
			BPointf p1(x + w / 2, y + h);
			BPointf p2(x + w, y);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Left_Fill:
		{
			BPointf p0(x, y + h / 2);
			BPointf p1(x + w, y + h);
			BPointf p2(x + w, y);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Right_Fill:
		{
			BPointf p0(x, y);
			BPointf p1(x, y + h);
			BPointf p2(x + w, y + h / 2);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftTop:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightTop:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.rightBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftBottom:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightBottom:
		{
			BPointf p0 = rect.rightTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftTop_Fill:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightTop_Fill:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.rightBottom();
			BPointf p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftBottom_Fill:
		{
			BPointf p0 = rect.leftTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightBottom_Fill:
		{
			BPointf p0 = rect.rightTop();
			BPointf p1 = rect.leftBottom();
			BPointf p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Minus:
		{
			BPointf p0(x, y + h / 2);
			BPointf p1(x + w, y + h / 2);
			drawLine(p0, p1);
			break;
		}
		case Graph_Plus:
		{
			BPointf p1(x + w / 2, y);
			BPointf p0(x + w / 2, y + h);
			BPointf p2(x, y + h / 2);
			BPointf p3(x + w, y + h / 2);
			drawLine(p0, p1);
			drawLine(p2, p3);
			break;
		}
		case Graph_Cross:
		{
			glEnable(GL_LINE_SMOOTH);
			drawLine(rect.leftTop(), rect.rightBottom());
			drawLine(rect.leftBottom(), rect.rightTop());
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Minimize:
		{
			BRectf minRect = rect % 50;
			drawLine(minRect.leftBottom(), minRect.rightBottom());
			break;
		}
		case Graph_Maximize:
		{
			BRectf maxRect = rect % 60;
			drawRect(maxRect);
			break;
		}
		case Graph_Normalize:
		{
			BRectf maxRect = rect % 50;
			drawRect(maxRect);
			break;
		}
		default:
			break;
		}
	}
}
void BPainter::drawGraph(const BRectd& rect, Graph graph)
{
	if (graph > Graph_None && graph < Graph_Max)
	{
		double x = rect.x();
		double y = rect.y();
		double w = rect.width();
		double h = rect.height();
		switch (graph)
		{
		case Graph_Circle:
		{
			double radius = bMin(rect.width(), rect.height());
			glEnable(GL_LINE_SMOOTH);
			drawCircle(rect.center(), radius / 2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Circle_Fill:
		{
			double radius = bMin(rect.width(), rect.height());
			glEnable(GL_MULTISAMPLE);
			fillCircle(rect.center(), radius / 2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Square:
		{
			drawRect(rect);
			break;
		}
		case Graph_Square_Fill:
		{
			fillRect(rect);
			break;
		}
		case Graph_Round:
		{
			glEnable(GL_LINE_SMOOTH);
			drawRoundRect(rect, rect.width() / 3, rect.height() / 3);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Round_Fill:
		{
			glEnable(GL_MULTISAMPLE);
			fillRoundRect(rect, rect.width() / 3, rect.height() / 3);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Up:
		{
			BPointd p1(x + w / 2, y);
			BPointd p0(x, y + h);
			BPointd p2(x + w, y + h);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Up_Fill:
		{
			BPointd p1(x + w / 2, y);
			BPointd p0(x, y + h);
			BPointd p2(x + w, y + h);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Down:
		{
			BPointd p0(x, y);
			BPointd p1(x + w / 2, y + h);
			BPointd p2(x + w, y);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Down_Fill:
		{
			BPointd p0(x, y);
			BPointd p1(x + w / 2, y + h);
			BPointd p2(x + w, y);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Left:
		{
			BPointd p0(x + w, y);
			BPointd p1(x, y + h / 2);
			BPointd p2(x + w, y + h);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Left_Fill:
		{
			BPointd p0(x, y + h / 2);
			BPointd p1(x + w, y + h);
			BPointd p2(x + w, y);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_Right:
		{
			BPointd p0(x, y);
			BPointd p1(x, y + h);
			BPointd p2(x + w, y + h / 2);
			glEnable(GL_LINE_SMOOTH);
			drawTriangle(p0, p1, p2);
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Arrow_Right_Fill:
		{
			BPointd p0(x, y);
			BPointd p1(x, y + h);
			BPointd p2(x + w, y + h / 2);
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftTop:
		{
			BPointd p0 = rect.leftTop();
			BPointd p1 = rect.leftBottom();
			BPointd p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightTop:
		{
			BPointd p0 = rect.leftTop();
			BPointd p1 = rect.rightBottom();
			BPointd p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftBottom:
		{
			BPointd p0 = rect.leftTop();
			BPointd p1 = rect.leftBottom();
			BPointd p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightBottom:
		{
			BPointd p0 = rect.rightTop();
			BPointd p1 = rect.leftBottom();
			BPointd p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			drawTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftTop_Fill:
		{
			BPointd p0 = rect.leftTop();
			BPointd p1 = rect.leftBottom();
			BPointd p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightTop_Fill:
		{
			BPointd p0 = rect.leftTop();
			BPointd p1 = rect.rightBottom();
			BPointd p2 = rect.rightTop();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_LeftBottom_Fill:
		{
			BPointd p0 = rect.leftTop();
			BPointd p1 = rect.leftBottom();
			BPointd p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Arrow_RightBottom_Fill:
		{
			BPointd p0 = rect.rightTop();
			BPointd p1 = rect.leftBottom();
			BPointd p2 = rect.rightBottom();
			glEnable(GL_MULTISAMPLE);
			fillTriangle(p0, p1, p2);
			glDisable(GL_MULTISAMPLE);
			break;
		}
		case Graph_Minus:
		{
			BPointd p0(x, y + h / 2);
			BPointd p1(x + w, y + h / 2);
			drawLine(p0, p1);
			break;
		}
		case Graph_Plus:
		{
			BPointd p1(x + w / 2, y);
			BPointd p0(x + w / 2, y + h);
			BPointd p2(x, y + h / 2);
			BPointd p3(x + w, y + h / 2);
			drawLine(p0, p1);
			drawLine(p2, p3);
			break;
		}
		case Graph_Cross:
		{
			glEnable(GL_LINE_SMOOTH);
			drawLine(rect.leftTop(), rect.rightBottom());
			drawLine(rect.leftBottom(), rect.rightTop());
			glDisable(GL_LINE_SMOOTH);
			break;
		}
		case Graph_Minimize:
		{
			BRectd minRect = rect % 50;
			drawLine(minRect.leftBottom(), minRect.rightBottom());
			break;
		}
		case Graph_Maximize:
		{
			BRectd maxRect = rect % 60;
			drawRect(maxRect);
			break;
		}
		case Graph_Normalize:
		{
			BRectd maxRect = rect % 50;
			drawRect(maxRect);
			break;
		}
		default:
			break;
		}
	}
}

void BPainter::drawBackground(State state)
{
	if (!member.widget)
		return;
	if (!(member.state.paint & Paint_Background))
		return;

	if (!state && !member.state.enabled)
		state = State_Disable;
	if (!state && member.state.actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	BRecti backRect = member.widget->size();
	if (bind(Image_Background, state))
	{
		glColor4ub(0, 0, 0, 255);
		if (IRound* round = widget_member(member.widget)->round)
		{
			glEnable(GL_MULTISAMPLE);
			glBegin(GL_TRIANGLE_FAN);
			for (int i = 0; i < round->backgroundPoints.size(); i++)
			{
				const BPointf& p = round->backgroundPoints[i];
				float tx = (p.x() - backRect.x()) / backRect.width();
				float ty = (p.y() - backRect.bottom()) / backRect.height();
				glTexCoord2f(tx, ty);
				glVertex2f(p.x(), p.y());
			}
			glEnd();
			glDisable(GL_MULTISAMPLE);
		}
		else
		{
			const BRect& crect = member.widget->centerRect();
			int left = crect.left() - backRect.left();
			int top = crect.top() - backRect.top();
			int right = backRect.right() - crect.right();
			int bottom = backRect.bottom() - crect.bottom();
			fillRect(backRect, BMargin(left, top, right, bottom));
		}
		unbind();
		return;
	}
	if (setColor(Color_Background, state))
	{
		if (IRound* round = widget_member(member.widget)->round)
		{
			glEnable(GL_MULTISAMPLE);
			glBegin(GL_TRIANGLE_FAN);
			for (int i = 0; i < round->backgroundPoints.size(); i++)
			{
				const BPointf& p = round->backgroundPoints[i];
				glVertex2f(p.x(), p.y());
			}
			glEnd();
			glDisable(GL_MULTISAMPLE);
		}
		else
		{
			fillRect(backRect);
		}
	}
}
void BPainter::drawForeground(State state)
{
	if (!member.widget)
		return;
	if (!(member.state.paint & Paint_Foreground))
		return;

	if (!state && !member.state.enabled)
		state = State_Disable;
	if (!state && member.state.actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	if (!setColor(Color_Foreground, state))
		return;
	BRecti foreRect = member.widget->centerRect();
	if (IRound* round = widget_member(member.widget)->round)
	{
		glEnable(GL_MULTISAMPLE);
		if (const BImage* image = member.findImage(Image_Foreground + state))
		{
			bind(image);
			glColor4ub(0, 0, 0, 255);
			glBegin(GL_TRIANGLE_FAN);
			for (int i = 0; i < round->centerPoints.size(); i++)
			{
				const BPointf& p = round->centerPoints[i];
				float tx = (p.x() - foreRect.x()) / foreRect.width();
				float ty = (foreRect.bottom() - p.y()) / foreRect.height();
				glTexCoord2f(tx, ty);
				glVertex2f(p.x(), p.y());
			}
			glEnd();
			unbind();
		}
		else
		{
			glBegin(GL_TRIANGLE_FAN);
			for (int i = 0; i < round->centerPoints.size(); i++)
			{
				const BPointf& p = round->centerPoints[i];
				glVertex2f(p.x(), p.y());
			}
			glEnd();
		}
		glDisable(GL_MULTISAMPLE);
	}
	else
	{
		if (const BImage* image = member.findImage(Image_Foreground + state))
			drawImage(foreRect, image);
		else
			fillRect(foreRect);
	}
}
void BPainter::drawPerch(State state)
{
	if (!member.widget)
		return;
	if (!(member.state.paint & Paint_Perch))
		return;

	if (!state && !member.state.enabled)
		state = State_Disable;
	if (!state && member.state.actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	const BPerch& perch = widget_member(member.widget)->perch;
	if (perch == BPerch())
		return;

	if (bind(Image_Perch, state))
	{
		glColor4ub(0, 0, 0, 255);
		int b = member.widget->border();
		int left = perch.left();
		int top = perch.top();
		int right = perch.right();
		int bottom = perch.bottom();
		int w = member.widget->width() - b - b;
		int h = member.widget->height() - b - b;
		int tw = member.tsize.width();
		int th = member.tsize.height();
		member_BWidget* wm = widget_member(member.widget);
		fillRect(wm->rectLeft, BRect(0, top, left, th - top - bottom));
		fillRect(wm->rectTop, BRect(left, 0, tw - left - right, top));
		fillRect(wm->rectRight, BRect(tw - left, top, right, th - top - bottom));
		fillRect(wm->rectBottom, BRect(left, th - bottom, tw - left - right, bottom));
		fillRect(wm->rectLeftTop, BRect(0, 0, left, top));
		fillRect(wm->rectRightTop, BRect(tw - right, 0, right, top));
		fillRect(wm->rectLeftBottom, BRect(0, th - bottom, left, bottom));
		fillRect(wm->rectRightBottom, BRect(tw - right, th - bottom, right, bottom));
		unbind();
		return;
	}
	if (setColor(Color_Perch, state))
	{
		if (IRound* round = widget_member(member.widget)->round)
		{
			glEnable(GL_MULTISAMPLE);
			fillTriangles(round->perchPoints);
			glDisable(GL_MULTISAMPLE);
		}
		else
		{
			member_BWidget* wm = widget_member(member.widget);
			fillRect(wm->rectLeft);
			fillRect(wm->rectTop);
			fillRect(wm->rectRight);
			fillRect(wm->rectBottom);
			fillRect(wm->rectLeftTop);
			fillRect(wm->rectLeftBottom);
			fillRect(wm->rectRightTop);
			fillRect(wm->rectRightBottom);
		}
	}
}
void BPainter::drawMargin(State state)
{
	if (!member.widget)
		return;
	if (!(member.state.paint & Paint_Margin))
		return;

	if (!state && !member.state.enabled)
		state = State_Disable;
	if (!state && member.state.actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	const BMargin& margin = member.widget->margin();
	if (margin == BMargin())
		return;

	const BRecti& crect = member.widget->centerRect();
	int w = member.widget->width();
	int h = member.widget->height();

	int left = margin.left();
	int top = margin.top();
	int right = margin.right();
	int bottom = margin.bottom();

	if (bind(Image_Margin, state))
	{
		glColor4ub(0, 0, 0, 255);
		int w = member.widget->width();
		int h = member.widget->height();
		int tw = member.tsize.width();
		int th = member.tsize.height();
		fillRect(crect.left() - left, crect.top(), left, crect.height(), BRect(0, top, left, th - top - bottom));
		fillRect(crect.left(), crect.top() - top, crect.width(), top, BRect(left, 0, tw - left - right, top));
		fillRect(crect.right(), crect.top(), right, crect.height(), BRect(tw - right, top, right, th - top - bottom));
		fillRect(crect.left(), crect.bottom(), crect.width(), bottom, BRect(left, th - bottom, tw - left - right, bottom));
		fillRect(crect.left() - left, crect.top() - top, left, top, BRect(0, 0, left, top));
		fillRect(crect.right(), crect.top() - top, right, top, BRect(tw - right, 0, right, top));
		fillRect(crect.left() - left, crect.bottom(), left, bottom, BRect(0, th - bottom, left, bottom));
		fillRect(crect.right(), crect.bottom(), right, bottom, BRect(tw - right, th - bottom, right, bottom));
		unbind();
		return;
	}
	if (setColor(Color_Margin, state))
	{
		if (IRound* round = widget_member(member.widget)->round)
		{
			glEnable(GL_MULTISAMPLE);
			fillTriangles(round->marginPoints);
			glDisable(GL_MULTISAMPLE);
		}
		else
		{
			int b = member.widget->border();
			const BPerch& perch = member.widget->perch();
			int pleft = perch.left();
			int ptop = perch.top();
			int pright = perch.right();
			int pbottom = perch.bottom();

			if (left > 0)
			{
				fillRect(b + pleft, b + ptop + top, left, crect.height());
			}
			if (top > 0)
			{
				fillRect(b + pleft + left, b + ptop, crect.width(), top);
			}
			if (right > 0)
			{
				fillRect(w - b - pright - right, b + ptop + top, right, crect.height());
			}
			if (bottom > 0)
			{
				fillRect(b + pleft + left, h - b - pbottom - bottom, crect.width(), bottom);
			}

			BRecti left_top_rect(b + pleft, b + ptop, left, top);
			if (left_top_rect.valid())
				fillRect(left_top_rect);

			BRecti left_bottom_rect(b + pleft, h - b - pbottom - bottom, left, bottom);
			if (left_bottom_rect.valid())
				fillRect(left_bottom_rect);

			BRecti right_top_rect(w - b - pright - right, b + ptop, right, top);
			if (right_top_rect.valid())
				fillRect(right_top_rect);

			BRecti right_bottom_rect(w - b - pright - right, h - b - pbottom - bottom, right, bottom);
			if (right_bottom_rect.valid())
				fillRect(right_bottom_rect);
		}
	}
}
void BPainter::drawBorder(State state)
{
	if (!member.widget)
		return;
	if (!(member.state.paint & Paint_Border))
		return;

	int b = member.widget->border();
	if (b < 1)
		return;

	if (!state && !member.state.enabled)
		state = State_Disable;
	if (!state && member.state.actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	if (bind(Image_Border, state))
	{
		glColor4ub(0, 0, 0, 255);
		int w = member.widget->width();
		int h = member.widget->height();
		int tw = member.tsize.width();
		int th = member.tsize.height();
		fillRect(0, b, b, h - b - b, BRect(0, b, b, th - b - b));
		fillRect(b, 0, w - b - b, b, BRect(b, 0, tw - b - b, b));
		fillRect(w - b, b, b, h - b - b, BRect(tw - b, b, b, th - b - b));
		fillRect(b, h - b, w - b - b, b, BRect(b, th - b, tw - b - b, b));
		fillRect(0, 0, b, b, BRect(0, 0, b, b));
		fillRect(w - b, 0, b, b, BRect(tw - b, 0, b, b));
		fillRect(0, h - b, b, b, BRect(0, th - b, b, b));
		fillRect(w - b, h - b, b, b, BRect(tw - b, th - b, b, b));
		unbind();
		return;
	}
	if (setColor(Color_Border, state))
	{
		if (IRound* round = widget_member(member.widget)->round)
		{
			glEnable(GL_MULTISAMPLE);
			fillTriangles(round->borderPoints);
			glDisable(GL_MULTISAMPLE);
		}
		else
		{
			int w = member.widget->width();
			int h = member.widget->height();
			fillRect(0, b, b, h - b - b);
			fillRect(0, 0, w, b);
			fillRect(w - b, b, b, h - b - b);
			fillRect(0, h - b, w, b);
		}
	}
}
void BPainter::drawTitle(State state)
{
	if (!member.widget)
		return;
	if (!(member.state.paint & Paint_Title))
		return;

	BRect titleRect = member.widget->rect(Part_Top);
	const BPerch& perch = member.widget->perch();
	titleRect.left() -= perch.left();
	titleRect.right() += perch.left();
	if (titleRect.empty())
		return;

	if (!state && !member.state.enabled)
		state = State_Disable;
	if (!state && member.state.actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	if (const BImage* image = member.findImage(Image_Title + state))
	{
		bind(image);
		fillRect(titleRect, member.state.titleMargin);
		unbind();
		return;
	}
	if (const BStyle* titleStyle = member.state.titleStyle)
	{
		if (const BImage* image = titleStyle->value(Value_Image))
		{
			bind(image);
			fillRect(titleRect, member.state.titleMargin);
			unbind();
			return;
		}
	}
	if (IRound* round = widget_member(member.widget)->round)
	{
		if (setColor(Color_Title, state))
		{
			glEnable(GL_MULTISAMPLE);
			fillTriangles(round->titlePoints);
			glDisable(GL_MULTISAMPLE);
		}
	}
	else
	{
		if (setColor(Color_Title, state))
			fillRect(titleRect);
	}

}
